2012-03-07 14 views
6

acabo de leer sobre mode_t que básicamente almacena la siguiente información:¿Por qué mode_t usa 4 bytes?

  • 7 valores booleanos para el tipo de archivo (los siguientes: S_IFREG, S_IFDIR, S_IFCHR, S_ISBLK, S_ISFIFO, S_ISLINK, S_ISSOCK)
  • 3 * 3 = 9 valores booleanos para los permisos de acceso (leer, escribir y ejecutar para propietario, grupo y otros)

Necesita 16 bit = 2 bytes. Supongo que incluso podría tener un poco menos para el tipo de archivo, ya que tiene que ser un archivo normal, un directorio, un dispositivo de caracteres o de bloque, un socket, un enlace simbólico o un conducto. ¿O existen otros tipos de archivos?

por lo que he acabo de comprobar el tamaño de mode_t con

printf("Size: %d byte\n", sizeof(mode_t)); 

Se utiliza 4 bytes. ¿Por qué usa 4 bytes? ¿Hay alguna información adicional que no haya notado?

edit: acabo he encontrado que mode_t se define en ptypes.inc:

type mode_t = cuint32; 

cuint32 es una de 32 bits de tamaño, entero sin signo y se define en ctypes.inc:

type cuint32 = LongWord; 

Quizás esto ayude a la respuesta.

+1

¿Qué sucede si se necesitan agregar más opciones/banderas, etc. en el futuro? – Nim

+0

Podría ser que simplemente se defina de un 'int', que es de 32 bits en la mayoría de las arquitecturas. O se ha hecho más grande para que pueda adaptarse a las futuras banderas. –

+0

Su ** int ** tipo _may_ puede ser de 4 bytes, incluso si almacena en él el número "255" ... El "bloque de construcción" es la arquitectura del procesador y, además, tiene espacio libre para cualquier otra bandera que tengan necesitar. ¡¡¡Odio las banderas de bit !!! –

Respuesta

9

Veamos lo que un compilador de "tonto" haría cuando se le da el siguiente código:

#include <stdio.h> 
#include <stdint.h> 

int main(int argc, char **argv) { 
    uint16_t test1 = 0x1122; 
    uint32_t test2 = 0x11223344; 
    if (test1 & 0x0100) 
    printf("yay1.\n"); 
    if (test2 & 0x00010000) 
    printf("yay2.\n"); 
} 

Este parece ser un caso de uso probable de valores de tipo mode_t, comprobando si se ha establecido una bandera. Ahora compilamos con gcc -O0 y comprobar el ensamblado generado:

0000000000000000 <main>: 
      ... 
    f: 66 c7 45 fe 22 11  movw $0x1122,-0x2(%rbp) 
    15: c7 45 f8 44 33 22 11 movl $0x11223344,-0x8(%rbp) 
    1c: 0f b7 45 fe    movzwl -0x2(%rbp),%eax ; load test1 into %eax 
    20: 25 00 01 00 00   and $0x100,%eax 
    25: 85 c0     test %eax,%eax 
      ... 
    33: 8b 45 f8    mov -0x8(%rbp),%eax ; load test2 into %eax 
    36: 25 00 00 01 00   and $0x10000,%eax 
    3b: 85 c0     test %eax,%eax 
      ... 

Vea cómo es necesaria la instrucción especial movzwl para cargar el valor de 16 bits? Esto se debe a que se debe extender la firma a dos bytes adicionales para que quepan en el registro. Obviamente, esta instrucción es más compleja que un simple mov. Esto podría tener un pequeño impacto en el rendimiento, y podría aumentar el tamaño del ejecutable en algunos bytes, lo que por sí solo no sería tan malo.

Sin embargo, si consideramos que no habría ventaja en el uso de un valor de 16 bits, dado que generalmente tomaría 32 bits de almacenamiento debido a la alineación, está claro por qué los diseñadores eligen usar el tamaño de palabra nativo de la CPU aquí.