【发布时间】:2013-06-20 16:12:22
【问题描述】:
#include<stdio.h>
int main()
{
struct test
{
char c;
int y;
float r;
double d;
} t1;
printf("%d\n",sizeof(t1));
return 0;
}
输出: 24 在我的 gcc 4.3.2 Ubuntu 12.04
输出:20 在 Ideone Link for Running Code
我的解释: 我认为 24 是正确的。如果我错了,请纠正我?
- 第一个块将被字符“c”占用。 1 个字节为自己,后跟 3 个字节的填充。
- 第二个块将被整数'y'占用。 (在这种情况下不需要填充,因为整数是 4 字节。所以它将完全填充块)。
- 第三块将被浮动'r'占用。 (不需要填充,因为 float 也是 4 个字节)。
- 现在将填充下一个 4 字节的块,因为 next 是双倍的。并且存储地址必须是该数据类型大小的倍数。
- 接下来的 2 个 4 字节的块将被双变量占用。
因此Size = 1(char) + 3(Padded in Char case) + 4(int) + 4(float) + 4(padded for Double) + 8(double) = 24
为了清楚起见:
由于块是在 4 字节集合中获取的。所以每个地址都是 4 的倍数。 对于 double ,下一个地址必须是 1012。但它不是 8 的倍数。所以填充它!从 1016 开始 我的问题 - 24 是正确的,我的解释是正确的还是我的解释是错误的,请解释一下?
【问题讨论】:
-
这里可能 20 和 24 都不正确。如果您看到一只黑猫,然后又看到一只白猫,那么无论出于何种原因,都没有理由认为黑色是猫的“正确”颜色。
-
但 24 是我在运行代码之前对这个问题的回答。我认为 24 也可以从逻辑上解释它!
-
对齐是实现定义的。有些编译器可能会为双精度添加填充,有些可能不会,也不是“正确的”。至少这是我的理解。
-
有些机器允许
double被打包在一个4字节的边界上;其他要求double在 8 字节边界上打包。您所描述的对于必须在 8 字节边界上打包double的系统是正确的; ideone 给出的对于double必须打包在 4 字节边界上的系统是正确的。因此,对于任何给定的系统,两者都可能是正确的。通常,只有其中一个是正确的。尽管同一台机器上的两个不同编译器可能具有不同的结构打包规则,但在实践中这不太可能成为问题——请参阅 ABI(应用程序二进制接口)。 -
%d格式适用于int;对于size_t,使用%zu,或者,如果您的实现不支持它(它是C99 中的“新”),则转换为int:printf("%d\n", (int)sizeof t1);. And a very minor quibble:int main()` 应该是int main(void)。