- 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 \\\,sizeof(mode_t));它使用4个字节。为什么使用4个字节?是否有任何额外的信息我没有注意到?
编辑:我刚刚发现mode_t是在ptypes.inc中定义的:
type mode_t = cuint32;cuint32是一个32位大小的无符号整数,在ctypes.inc中定义:
type cuint32 = LongWord;也许这有助于解答。
解决方案让我们来看看给定以下代码时哑编译器会做什么:
#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.\\\); if(test2& 0x00010000) printf(yay2.\\\); $ b $ p $ b类似于 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 $ 0 x11223344,-0x8(%rbp) 1c:0f b7 45 fe movzwl -0x2(%rbp),%eax;将test1加载到%eax 20:25 00 01 00 00和$ 0x100,%eax 25:85 c0 test%eax,%eax ... 33:8b 45 f8 mov -0x8(%rbp),%eax;将test2加载到%eax 36:25 00 00 01 00和$ 0x10000,%eax 3b:85 c0 test%eax,%eax ...查看特殊的 movzwl 指令是如何加载16位值?这是因为它需要符号扩展到两个额外的字节以适应寄存器。显然,这个指令比简单的 mov 复杂。这可能会对性能产生很小的影响,并且可能会使可执行文件的大小增加一些字节,本身不会太糟糕。
但是,如果我们考虑在使用16位值的时候没有任何优势,因为它们通常会由于对齐而占用32位的存储空间,这就清楚了为什么设计者选择在这里使用CPU的本地字大小。
I've just read about mode_t that it basically stores the following information:
- 7 boolean values for the file type (S_IFREG, S_IFDIR, S_IFCHR, S_ISBLK, S_ISFIFO, S_ISLINK, S_ISSOCK)
- 3*3 = 9 boolean values for the access permissons (read, write and execute for owner, group and others)
So it needs 16 bit = 2 bytes. I guess you could even have one bit less for the file type, as it has to be either a regular file, a directory, a character or block device, a socket, a symbolic link, or a pipe. Or do other file types exist?
So I've just checked the size of mode_t with
printf("Size: %d byte\n", sizeof(mode_t));It uses 4 byte. Why does it use 4 byte? Is there any additional information I didn't notice?
edit: I've just found that mode_t is defined in ptypes.inc:
type mode_t = cuint32;cuint32 is a 32 bits sized, unsigned integer and defined in ctypes.inc:
type cuint32 = LongWord;Perhaps this helps for the answer.
解决方案Let's look at what a "dumb" compiler would do when given the following code:
#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"); }This seems like a likely use case for values of type mode_t, checking if a flag is set. Now we compile it with gcc -O0 and check the generated assembly:
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 ...See how the special movzwl instruction is needed to load the 16-bit value? This is because it needs to be sign-extended to two additional bytes to fit in the register. Obviously this instruction is more complex than a simple mov. This might have a tiny impact on performance, and it might increase the executable size by some bytes, which by itself wouldn't be too bad.
However, if we consider that there would be no advantage in using a 16-bit value, because it would usually take up 32 bits of storage anyway due to alignment, it's clear why the designers choose to use the native word size of the CPU here.
更多推荐
为什么mode
发布评论