使用带有数组和指针的sizeof的实验

sjs*_*sam 21 c arrays pointers sizeof

对于该计划:

#include<stdio.h>
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;
}
Run Code Online (Sandbox Code Playgroud)

输出是:

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

问题/观察(案例顺序):

  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一致

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

Moh*_*ain 15

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

  1. 为案例1输出20,因为b被宣布为arrayintegers即int[]?Fact1确认返回总块数(以字节为单位).不是吗?

是的,结果显示了sizeof(int [5]).所以从Fact1,大小是5*4

  1. 我猜铸造bint*这里所作的区别.这里b被认为是一个指针.我使用Fact2证实了这一点.对还是错?

对.但是添加更多信息:sizeof只需要表达式,它不会计算表达式(值),除非它是VLA类型.(从节6.5.3.4中的sizeof操作者C99规格)

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

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

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

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

a作为指向数组2的指针int.所以打印的大小是指针(到int数组).

int (*a)[2];声明a为指向数组2的指针int.所以你得到的大小pointer to array.

要获得所需的结果(指针数组2的大小int),请使用:int *a[2];

int (*a)[2];

a           anonymous
+----+      +----+----+
| a  |----->|int |int |
+----+      +----+----+

int *b[2];

b  
+----+----+
|int*|int*|
+----+----+
b[0] b[1]
Run Code Online (Sandbox Code Playgroud)
  1. a[0]是指针.输出与Fact2一致
  2. a[2]是指针.输出与Fact2一致

如前所述,a是一个指向数组2的指针int.所以a[index]是一个数组2如果int.所以,类型a[0]a[1]是数组2 int.因此输出2*4来自事实1.
可能与此答案无关,但未a初始化并在表达式中使用它会导致未定义的行为.虽然使用起来很好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]
Run Code Online (Sandbox Code Playgroud)

一个便携式程序(并非万无一失)确认类型的样子:

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


dbu*_*ush 13

所述sizeof操作者是可以的阵列之间进行区分(假定它不是一个函数参数)和指针的几件事情之一.

  1. b被识别为5个元素的数组,每个元素是4个字节,因此sizeof(b)计算结果为20.
  2. 强制转换将数组转换为指针的方式与将函数传递给函数的方式类似.所以大小是8.
  3. 这实际上并没有衰减到指针.这一个指针.你拿的是地址int,所以当然是类型int *.解决一个注释,如果将表达式&b[0]传递给函数,表达式会衰减到指针仍然是不准确的,因为它实际上是指针而不是数组.
  4. 因为a是指向数组的指针,所以大小是指针的大小,即8.这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]);
Run Code Online (Sandbox Code Playgroud)

输出:

a00=1
a01=2
a10=3
a11=4
a20=5
a21=6
Run Code Online (Sandbox Code Playgroud)

将2D数组传递给函数时也可以使用它:

void f(int (*a)[2]) 
{
    ...
}

int main()
{
    int x[3][2];
    f(x);
}
Run Code Online (Sandbox Code Playgroud)