对数组和指针使用 sizeof 的实验
Experiments using sizeof with arrays and pointers
对于程序:
#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;
}
输出为:
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
Questions/Observations(以大小写顺序):
案例 1 输出 20 是因为 b
被声明为整数数组,即 int[]
?返回以字节为单位的总块数,由 Fact1 确认。不是吗?
我想将 b
转换为 int*
会有所不同。这里 b
是
被认为是一个指针。我使用 Fact2 确认了这一点。对还是错?
&b[0]
衰减为指针 b
。输出与 Fact2 一致。
I expected 16 这里但我得到 8 作为输出。我得出结论,这是因为 a
毕竟是一个指针,输出与 Fact2 一致。我得到了类似于问题 2 的输出。
a[0]
是指针。输出与 Fact2
重合
a[1]
是指针。输出与 Fact2
重合
请回答问题,如有错误请指正。
Please answer the questions and correct me if any of the observations
are wrong.
- Is Case 1 output
20
because b
was declared as an array
of int
egers ie int[]
? The total block in bytes is returned as confirmed by Fact1. Isn't it?
是的,结果显示sizeof(int [5])
。所以从 Fact1 来看,大小是 5*4
- I guess casting
b
to int*
made the difference here. Here b
is considered a pointer. I confirmed this using Fact2. Right or wrong?
没错。但是添加更多信息:sizeof
只需要表达式的类型,它 不会 评估表达式(对于值),除非它是 VLA 类型。
(来自 6.5.3.4 sizeof operator of C99 specs)
因为您正在对最终结果应用强制转换,所以之后的任何内容都无关紧要。
&b[0]
decays to a pointer b
. The output coincides with Fact2 .
不,是的。 b[0]
的类型是 int
,因此 &b[0]
的类型已经是 int *
(回想一下 [...]
比 &
绑定得更紧)。没有腐烂。是的,输出与 Fact2 一致。
- I expected 16 here but I got 8 as the output. I concluded that this is because a is afterall a pointer and the output coincides with Fact2 . I got the output similar to Question 2.
a
作为指向 int
的数组 2 的指针。所以打印的大小是指针(指向 int
数组)。
int (*a)[2];
将 a
声明为指向 int
的数组 2 的指针。所以你得到 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]
is pointer. The output coincides with Fact2
a[2]
is pointer. The output coincides with Fact2
如前所述,a
是指向int
数组2的指针。所以 a[index]
是一个数组 2 if int
。因此,a[0]
和 a[1]
的类型是 int
的数组 2。所以输出是来自事实 1 的 2*4
。
可能与这个答案无关,但是 a
未初始化并且在表达式中使用它会导致 undefined behaviour。虽然可以在 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]
一个portable program (not foolproof) to confirm the types看起来像:
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
是一个指向数组的指针,所以size就是一个指针的大小,即8。这和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,因为它是一个包含 2 个元素的大小为 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
将二维数组传递给函数时也可以使用它:
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)
。下面SO post详细阐述
希望这对您的话题有所帮助。
对于程序:
#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;
}
输出为:
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
Questions/Observations(以大小写顺序):
案例 1 输出 20 是因为
b
被声明为整数数组,即int[]
?返回以字节为单位的总块数,由 Fact1 确认。不是吗?我想将
b
转换为int*
会有所不同。这里b
是 被认为是一个指针。我使用 Fact2 确认了这一点。对还是错?&b[0]
衰减为指针b
。输出与 Fact2 一致。I expected 16 这里但我得到 8 作为输出。我得出结论,这是因为
a
毕竟是一个指针,输出与 Fact2 一致。我得到了类似于问题 2 的输出。a[0]
是指针。输出与 Fact2 重合
a[1]
是指针。输出与 Fact2 重合
请回答问题,如有错误请指正。
Please answer the questions and correct me if any of the observations are wrong.
- Is Case 1 output
20
becauseb
was declared as anarray
ofint
egers ieint[]
? The total block in bytes is returned as confirmed by Fact1. Isn't it?
是的,结果显示sizeof(int [5])
。所以从 Fact1 来看,大小是 5*4
- I guess casting
b
toint*
made the difference here. Hereb
is considered a pointer. I confirmed this using Fact2. Right or wrong?
没错。但是添加更多信息:sizeof
只需要表达式的类型,它 不会 评估表达式(对于值),除非它是 VLA 类型。
(来自 6.5.3.4 sizeof operator of C99 specs)
因为您正在对最终结果应用强制转换,所以之后的任何内容都无关紧要。
&b[0]
decays to a pointerb
. The output coincides with Fact2 .
不,是的。 b[0]
的类型是 int
,因此 &b[0]
的类型已经是 int *
(回想一下 [...]
比 &
绑定得更紧)。没有腐烂。是的,输出与 Fact2 一致。
- I expected 16 here but I got 8 as the output. I concluded that this is because a is afterall a pointer and the output coincides with Fact2 . I got the output similar to Question 2.
a
作为指向 int
的数组 2 的指针。所以打印的大小是指针(指向 int
数组)。
int (*a)[2];
将 a
声明为指向 int
的数组 2 的指针。所以你得到 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]
is pointer. The output coincides with Fact2a[2]
is pointer. The output coincides with Fact2
如前所述,a
是指向int
数组2的指针。所以 a[index]
是一个数组 2 if int
。因此,a[0]
和 a[1]
的类型是 int
的数组 2。所以输出是来自事实 1 的 2*4
。
可能与这个答案无关,但是 a
未初始化并且在表达式中使用它会导致 undefined behaviour。虽然可以在 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]
一个portable program (not foolproof) to confirm the types看起来像:
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
是一个指向数组的指针,所以size就是一个指针的大小,即8。这和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,因为它是一个包含 2 个元素的大小为 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
将二维数组传递给函数时也可以使用它:
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)
。下面SO post详细阐述
希望这对您的话题有所帮助。