为什么mode_t使用4个字节?

Mar*_*oma 6 c filesystems permissions

我刚刚读到有关mode_t的信息,它基本上存储了以下信息:

  • 7个文件类型的布尔值(S_IFREG,S_IFDIR,S_IFCHR,S_ISBLK,S_ISFIFO,S_ISLINK,S_ISSOCK)
  • 3*3 =访问权限的9个布尔值(所有者,组和其他人的读,写和执行)

所以它需要16位= 2个字节.我猜你甚至可以少一点文件类型,因为它必须是常规文件,目录,字符或块设备,套接字,符号链接或管道.或者存在其他文件类型?

所以我刚刚检查了mode_t的大小

printf("Size: %d byte\n", sizeof(mode_t));
Run Code Online (Sandbox Code Playgroud)

它使用4个字节.为什么使用4字节?有没有我没注意到的其他信息?

编辑:我刚刚发现mode_t在ptypes.inc中定义:

type mode_t = cuint32;
Run Code Online (Sandbox Code Playgroud)

cuint32是一个32位大小的无符号整数,在ctypes.inc中定义:

type cuint32 = LongWord;
Run Code Online (Sandbox Code Playgroud)

也许这有助于答案.

Nik*_* B. 10

让我们看一下"dumb"编译器在给出以下代码时会做什么:

#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");
}
Run Code Online (Sandbox Code Playgroud)

这似乎是类型值的可能用例mode_t,检查是否设置了标志.现在我们编译它gcc -O0并检查生成的程序集:

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
            ...
Run Code Online (Sandbox Code Playgroud)

看看如何movzwl加载16位值需要特殊指令?这是因为它需要符号扩展到另外两个字节以适合寄存器.显然这条指令比简单的更复杂mov.这可能对性能产生很小的影响,并且可能会将可执行文件大小增加几个字节,这本身就不会太糟糕.

但是,如果我们认为使用16位值没有优势,因为由于对齐,它通常会占用32位存储空间,因此很明显为什么设计人员选择在这里使用CPU的本机字大小.