使用带有数组和指针的sizeof的实验
对于该计划:
#include int main(void) { int (*a)[2]; int b[5]; printf("sizeof(int) : %zu\n", sizeof(int)); printf("sizeof(int*) : %zu\n", sizeof(int*)); printf("sizeof(b) : %zu\n",sizeof(b)); printf("sizeof((int*)b) : %zu\n",sizeof((int*)b)); printf("sizeof(&b[0]) : %zu\n",sizeof(&b[0])); printf("sizeof(a) : %zu\n",sizeof(a)); printf("sizeof(a[0]) : %zu\n",sizeof(a[0])); printf("sizeof(a[1]) : %zu\n",sizeof(a[1])); return 0; }
输出是:
sizeof(int) : 4 -> Fact 1 sizeof(int*) : 8 -> Fact 2 sizeof(b) : 20 -> Case 1 sizeof((int*)b) : 8 -> Case 2 sizeof(&b[0]) : 8 -> Case 3 sizeof(a) : 8 -> Case 4 sizeof(a[0]) : 8 -> Case 5 sizeof(a[1]) : 8 -> Case 6
问题/观察(案例顺序):
-
情况1输出20是因为
b
被声明为整数数组,即int[]
? Fact1确认返回总块数(以字节为单位)。 不是吗? -
我想把
b
成int*
在这里有所不同。 这里b
被认为是一个指针。 我使用Fact2证实了这一点。 对还是错? -
&b[0]
衰减到指针b
。 输出与Fact2一致。 -
我在这里预计 16,但我得到8作为输出。 我的结论是,这是因为
a
是一个指针,输出与Fact2重合。 我的输出类似于问题2。 -
a[0]
是指针。 输出与Fact2一致 -
a[1]
是指针。 输出与Fact2一致
如果任何观察结果有误,请回答问题并纠正我。
如果任何观察结果有误,请回答问题并纠正我。
- 案例1输出
20
是因为b
被声明为一个int
egersarray
,即int[]
? Fact1确认返回总块数(以字节为单位)。 不是吗?
是的,结果显示sizeof(int [5])
。 所以从Fact1开始,尺寸为5*4
- 我想把
b
成int*
在这里有所不同。 这里b
被认为是一个指针。 我使用Fact2证实了这一点。 对还是错?
对。 但是添加更多信息: sizeof
只需要表达式,它不会计算表达式(值),除非它是VLA类型。 (摘自第6.5.3.4节C99规格的 尺寸操作员 )
因为您在最终结果上应用演员表,所以之后的任何事情都无关紧要。
&b[0]
衰减到指针b
。 输出与Fact2一致。
不,是的。 b[0]
类型是int
,因此&b[0]
类型已经是int *
(回想[...]
比&
更紧密。 没有腐朽。 是的,输出与Fact2重合。
- 我在这里预计16,但我得到8作为输出。 我的结论是,这是因为a是一个指针,输出与Fact2重合。 我的输出类似于问题2。
a
指向int
数组2的指针。 所以打印的大小是指针(到一个int
数组)。
int (*a)[2];
声明a
指向int
数组2的指针。 所以你得到pointer to array
的pointer to array
的大小。
要获得所需的结果(指向int
的数组2的大小),请使用: int *a[2];
int (*a)[2]; a anonymous +----+ +----+----+ | a |----->|int |int | +----+ +----+----+ int *b[2]; b +----+----+ |int*|int*| +----+----+ b[0] b[1]
a[0]
是指针。 输出与Fact2一致a[2]
是指针。 输出与Fact2一致
如前所述, a
是指向int
数组2的指针。 所以如果是int
a[index]
是一个数组2。 因此, a[0]
和a[1]
是int
数组2。 因此事实1的输出是2*4
。
可能与此答案无关,但a
未初始化并在表达式中使用它会导致未定义的行为 。 虽然在sizeof
使用很好
为了理解输出,让我们分析sizeof
的参数sizeof
printf("sizeof(b) : %zu\n",sizeof(b)); // int [5] printf("sizeof((int*)b) : %zu\n",sizeof((int*)b)); // int * printf("sizeof(&b[0]) : %zu\n",sizeof(&b[0])); // int * printf("sizeof(a) : %zu\n",sizeof(a)); // int (*) [2] printf("sizeof(a[0]) : %zu\n",sizeof(a[0])); // int [2] printf("sizeof(a[1]) : %zu\n",sizeof(a[1])); // int [2]
用于确认类型的便携式程序(非万无一失)如下所示:
assert(sizeof(b) == sizeof(int [5])); assert(sizeof((int*)b) == sizeof(int *)); assert(sizeof(&b[0]) == sizeof(int *)); assert(sizeof(a) == sizeof(int(*)[2])); assert(sizeof(a[0]) == sizeof(int[2])); assert(sizeof(a[1]) == sizeof(int[2]));
sizeof
运算符是可以区分数组(假设它不是函数参数)和指针的少数事物之一。
-
b
被识别为5个元素的数组,其中每个元素是4个字节,因此sizeof(b)
计算结果为20。 - 强制转换将数组转换为指针的方式与将函数传递给函数的方式类似。 所以大小是8。
- 这实际上并没有衰减到指针。 这是一个指针。 你正在获取
int
的地址,所以当然类型是int *
。 解决你的一条评论,如果将表达式&b[0]
传递给一个指针,如果将它传递给函数仍然是不准确的,因为它实际上是一个指针,而不是一个数组。 - 由于
a
是指向数组的指针,因此大小是指针的大小,即8.这与int *c[2]
不同,int *c[2]
是一个指针数组,大小为16。 -
a[0]
不是指针而是大小为2的数组 。 语法a[0]
等价于*(a + 0)
。 因此,由于a
是指向数组的指针,因此解引用a
会为我们提供一个数组。 由于每个元素是4个字节,因此大小为8.如果a
被定义为int (*a)[3]
则sizeof(a[0])
计算结果为12。 - 与数字5类似,
a[1]
是大小为2的数组。因此sizeof(a[1])
计算结果为8,因为它是一个包含4个大小为4的元素的数组。
如何使用a
的示例如下:
int (*a)[2]; int d[3][2]; a=d; d[0][0]=1; d[0][1]=2; d[1][0]=3; d[1][1]=4; d[2][0]=5; d[3][1]=6; printf("a00=%d\n",a[0][0]); printf("a01=%d\n",a[0][1]); printf("a10=%d\n",a[1][0]); printf("a11=%d\n",a[1][1]); printf("a20=%d\n",a[2][0]); printf("a21=%d\n",a[3][1]);
输出:
a00=1 a01=2 a10=3 a11=4 a20=5 a21=6
将2D数组传递给函数时也可以使用它:
void f(int (*a)[2]) { ... } int main() { int x[3][2]; f(x); }
这是关于这个主题的一些个人研究。 我在四种不同的环境中运行您的测试代码,两个64位和两个32位。
我使用了三种不同的编译器:llvm,gcc和mipsPro cc。
以下是结果的评论比较 :
// 64-bit environment - all compilers sizeof(int) : 4 -> Fact 1 -32 bit int -> 4 bytes sizeof(int*) : 8 -> Fact 2 -this and other pointers in a 64-bit system are 8-bytes long sizeof(b) : 20 -> Case 1 -array of 5 32 bit ints -> 20 bytes sizeof((int*)b) : 8 -> Case 2 sizeof(&b[0]) : 8 -> Case 3 sizeof(a) : 8 -> Case 4 sizeof(a[0]) : 8 -> Case 5 -array of two 4 byte ints sizeof(a[1]) : 8 -> Case 6 -array of two 4 byte ints // 32-bit environments - all compilers sizeof(int) : 4 -> Fact 1 -32 bit int -> 4 bytes sizeof(int*) : 4 -> Fact 2 -this and other pointers in a 32-bit system are 4-bytes long sizeof(b) : 20 -> Case 1 -array of 5 32 bit ints -> 20 bytes sizeof((int*)b) : 4 -> Case 2 sizeof(&b[0]) : 4 -> Case 3 sizeof(a) : 4- > Case 4 sizeof(a[0]) : 8 -> Case 5 -array of two 4 byte ints sizeof(a[1]) : 8 -> Case 6 -array of two 4 byte ints
解释 – 所有结果始终符合以下模式:
-
int
大小用于依赖于编译器,也许仍然依赖于AFAIK。 它在所有测试环境和编译器中都是4字节(事实1)。 - 所有指针的大小默认为环境,64位或32位(事实2,案例2,3,4)。
- 两个四字节整数的数组大小等于
2*sizeof(int)
(情况5,6)。 -
a[0]
可以改写为*a
;a[1]
也可以写成*(a + 1)
。 以下SOpost详细阐述了它。希望这可以为您的主题做出贡献。