使用带有数组和指针的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. 情况1输出20是因为b被声明为整数数组,即int[] ? Fact1确认返回总块数(以字节为单位)。 不是吗?

  2. 我想把bint*在这里有所不同。 这里b被认为是一个指针。 我使用Fact2证实了这一点。 对还是错?

  3. &b[0]衰减到指针b 。 输出与Fact2一致。

  4. 我在这里预计 16,但我得到8作为输出。 我的结论是,这是因为a是一个指针,输出与Fact2重合。 我的输出类似于问题2。

  5. a[0]是指针。 输出与Fact2一致

  6. a[1]是指针。 输出与Fact2一致

如果任何观察结果有误,请回答问题并纠正我。

如果任何观察结果有误,请回答问题并纠正我。

  1. 案例1输出20是因为b被声明为一个int egers array ,即int[] ? Fact1确认返回总块数(以字节为单位)。 不是吗?

是的,结果显示sizeof(int [5]) 。 所以从Fact1开始,尺寸为5*4

  1. 我想把bint*在这里有所不同。 这里b被认为是一个指针。 我使用Fact2证实了这一点。 对还是错?

对。 但是添加更多信息: sizeof只需要表达式,它不会计算表达式(值),除非它是VLA类型。 (摘自第6.5.3.4节C99规格的 尺寸操作员

因为您在最终结果上应用演员表,所以之后的任何事情都无关紧要。

  1. &b[0]衰减到指针b 。 输出与Fact2一致。

不,是的。 b[0]类型是int ,因此&b[0]类型已经是int * (回想[...]&更紧密。 没有腐朽。 是的,输出与Fact2重合。

  1. 我在这里预计16,但我得到8作为输出。 我的结论是,这是因为a是一个指针,输出与Fact2重合。 我的输出类似于问题2。

a指向int数组2的指针。 所以打印的大小是指针(到一个int数组)。

int (*a)[2]; 声明a指向int数组2的指针。 所以你得到pointer to arraypointer 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] 
  1. a[0]是指针。 输出与Fact2一致
  2. 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运算符是可以区分数组(假设它不是函数参数)和指针的少数事物之一。

  1. b被识别为5个元素的数组,其中每个元素是4个字节,因此sizeof(b)计算结果为20。
  2. 强制转换将数组转换为指针的方式与将函数传递给函数的方式类似。 所以大小是8。
  3. 这实际上并没有衰减到指针。 这一个指针。 你正在获取int的地址,所以当然类型是int * 。 解决你的一条评论,如果将表达式&b[0]传递给一个指针,如果将它传递给函数仍然是不准确的,因为它实际上是一个指针,而不是一个数组。
  4. 由于a是指向数组的指针,因此大小是指针的大小,即8.这与int *c[2]不同, int *c[2]是一个指针数组,大小为16。
  5. a[0]不是指针而是大小为2数组 。 语法a[0]等价于*(a + 0) 。 因此,由于a是指向数组的指针,因此解引用a会为我们提供一个数组。 由于每个元素是4个字节,因此大小为8.如果a被定义为int (*a)[3]sizeof(a[0])计算结果为12。
  6. 与数字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详细阐述了它。

    希望这可以为您的主题做出贡献。