2012-03-07 12 views
6

Właśnie przeczytałem o mode_t że w zasadzie przechowuje następujące informacje:Dlaczego tryb używa 4 bajtów?

  • 7 wartości logicznych dla typu pliku (S_IFREG, S_IFDIR, S_IFCHR, S_ISBLK, S_ISFIFO, S_ISLINK, S_ISSOCK)
  • 3 * 3 = 9 wartości boolowskich dla uprawnień dostępu (odczyt, zapis i wykonanie dla właściciela, grupy i innych)

Potrzebuje 16 bitów = 2 bajty. Sądzę, że możesz mieć nawet o jeden bit mniej dla tego typu pliku, ponieważ musi to być zwykły plik, katalog, znak lub urządzenie blokowe, gniazdo, dowiązanie symboliczne lub potok. Lub czy istnieją inne typy plików?

Więc ja właśnie sprawdzana wielkość mode_t z

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

Wykorzystuje 4 bajty. Dlaczego używa 4 bajtów? Czy są jakieś dodatkowe informacje, których nie zauważyłem?

edit: Właśnie okazało się, że mode_t jest zdefiniowana w ptypes.inc:

type mode_t = cuint32; 

cuint32 jest 32 bitów, bez znaku liczby całkowitej wielkości i zdefiniowane w ctypes.inc:

type cuint32 = LongWord; 

Być może to pomaga w odpowiedzi.

+1

co, jeśli w przyszłości trzeba będzie dodać więcej opcji/flag itp.? – Nim

+0

Może być tak, że jest po prostu wpisany z 'int', który w większości architektur ma 32 bity. Lub jest większy, dzięki czemu może pasować do przyszłych flag. –

+0

Twój ** int ** type _may_ to 4 bajty, nawet jeśli zapisujesz w nim numer "255" ... "Elementem konstrukcyjnym" jest architektura procesora, a ponadto masz trochę wolnego miejsca na jakąkolwiek inną flagę, którą będą potrzeba. OMG Nienawidzę bitflagów !!! –

Odpowiedz

9

Spójrzmy na to, co jest „głupi” kompilator zrobi, gdy biorąc pod uwagę następujący kod:

#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"); 
} 

Wydaje się prawdopodobnym przypadku użycia dla wartości typu mode_t, sprawdzenie, czy flaga jest ustawiona. Teraz musimy go skompilować z gcc -O0 i sprawdzić wygenerowany montaż:

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 
      ... 

Zobacz jak potrzebna jest specjalna instrukcja movzwl załadować wartości 16-bitowej? Dzieje się tak, ponieważ musi zostać rozszerzony o znak do dwóch dodatkowych bajtów, aby zmieścić się w rejestrze. Oczywiście ta instrukcja jest bardziej skomplikowana niż prosta mov. Może to mieć niewielki wpływ na wydajność i może zwiększyć rozmiar pliku wykonywalnego o kilka bajtów, co samo w sobie nie byłoby zbyt złe.

Jeśli jednak weźmiemy pod uwagę, że nie byłoby żadnej korzyści przy użyciu 16-bitowej wartości, ponieważ z powodu wyrównania zwykle zajmie to 32-bitowe miejsce, jasne jest, dlaczego projektanci zdecydowali się na użycie natywnego rozmiaru słowa CPU tutaj.

Powiązane problemy