void foo(int *arr) {
printf("%d\n", sizeof arr); // 4
}
int main(){
int arr[] = {1, 2, 3, 4, 5};
printf("%d\n", sizeof arr); // 20
foo(arr);
}
对于上述代码的sizeof
计算数组字节结果有些不太明白,arr
很显然和arr[0]
是等效的,为什么在主函数中计算arr
的大小等于20
(所有元素加起来的字节大小),而作为参数传递给另一个函数时却是4
?
1
ho121 2021-07-14 15:55:45 +08:00 via Android
数组传参后都是指针,指针大小在 32 位环境下是 4,64 位环境下是 8
|
3
qieqie 2021-07-14 15:59:15 +08:00
一个是指针一个是数组,第一个 arr 等效的是&arr[0]
|
4
ipwx 2021-07-14 16:16:34 +08:00
首先,指针和数组不等效。。。楼主你想当然地信仰了一个错误观点。
sizeof(int*) == 4 sizeof(int[5]) == 20 |
5
3dwelcome 2021-07-14 16:17:29 +08:00 1
@JQiue “但是为什么 sizeof 在主函数中却是计算数组的所有元素大小”
因为 C/C++是类型推导语言,但是函数参数传递中,会丢失原来的类型。 你在两个函数里,分别用 typeid(arr).name()打一下类型名称就知道了,两者不一样。 |
6
thinkIn 2021-07-14 16:37:42 +08:00 via iPhone
sizeof 一般是用 define 定义的,你可以看下原理,很简练
|
7
wudicgi 2021-07-14 16:45:13 +08:00
"arr 很显然和 arr[0]是等效的"
当然不是等效的,否则 sizeof(arr) / sizeof(arr[0]) 这种计算元素数量的方法还怎么工作 |
8
hanssx 2021-07-14 16:49:03 +08:00
|
9
lesismal 2021-07-14 17:04:26 +08:00
《 C 陷阱与缺陷》《 C 专家编程》《 C 和指针》了解一下
|
10
rshun 2021-07-14 17:06:12 +08:00
函数参数那个*arr 表示的是数组第一个元素,即 arr[0],所以你在函数内做 sizeof 的时候就是 4
你在 main 里面的做 sizeof,是数组的所有元素,所以是 4*5=20 |
11
echoechoin 2021-07-14 17:08:40 +08:00
数组传递到函数中会被转换为指针!!! 所以 sizeof (数组) != sizeof(指针)
|
12
ho121 2021-07-14 17:10:22 +08:00 via Android
@JQiue
主函数中,arr 依然是数组,所以 sizeof 的结果是数组大小。另一方面 arr 也可以作为表达式,它代表的是 arr 数组的首地址。 函数调用 foo(arr)中的 arr 是作为表达式出现的,所以是指针。sizeof arr 中的 arr 代表数组本身。 |
13
lesismal 2021-07-14 17:13:14 +08:00
国人写的印象中《 C 语言深度解剖》还不错,太久了,记不清了。还有本《狂人 C:程序员入门必备》我没看过,但是当初作者在论坛跟大家 PK 各种 C 问题,很多老伙计一块给提了不少勘误和意见,内容应该能靠谱些吧
刚还搜到一本日本人的《征服 C 指针》,也没读过,但是以前读过的一些日本作者的技术书籍,感觉都挺不错的 |
14
lesismal 2021-07-14 17:16:02 +08:00
多读几本好书就理解清楚了,C 的细节还挺多呢,这么零散着问,很难系统吸收知识点,建议猛读一下我推荐的那几本书
|
15
OliverDD 2021-07-14 17:52:14 +08:00
|
17
lakehylia 2021-07-14 18:21:09 +08:00
#include <cstdio>
void f1(int a[5]) { printf("f1 sizeof %zu\n", sizeof(a)); } void f2(int a[]) { printf("f2 sizeof %zu\n", sizeof(a)); } void f3(int* a) { printf("f3 sizeof %zu\n", sizeof(a)); } int main() { int a[5]; f1(a); f2(a); f3(a); return 0; } //======== 运行结果 f1 sizeof 8 f2 sizeof 8 f3 sizeof 8 |
18
lakehylia 2021-07-14 18:29:20 +08:00
C 中数组不能按值传递的规则。
但是 c++里面,引用有奇效 void f4(int(&a)[5]) { printf("f4 sizeof %zu\n", sizeof(a)); // f4 sizeof 20 } |
19
agagega 2021-07-14 19:16:08 +08:00 via iPhone
C 的数组不是指针,只是某些时候可以相互转换
|
20
LnTrx 2021-07-14 19:29:59 +08:00
在函数里无论是写成数组还是指针,实际上都是指针,数组大小的信息已经丢失了
https://www.geeksforgeeks.org/why-c-treats-array-parameters-as-pointers/ |
21
wwbfred 2021-07-14 20:00:10 +08:00
所以不喜欢用 C 数组,只是考题倒是很喜欢考。
你说它是个类型吧,它又不能传递;你说它不是类型吧,他还有自己的大小。 这种不一致的表现,放到别的地方,就叫做坑。 |
22
lonewolfakela 2021-07-15 09:34:22 +08:00
@thinkIn 啥,哪家编译器的 sizeof 是用 define 定义的?
|
23
7075 2021-07-15 09:44:52 +08:00 1
C/C++数组传参,是传指针。在定义处,编译器有保留数组类型及数组长度的信息,所以可以用 sizeof 求长度。传参后参数类型转为指针,你 sizeof 求的是指针的 size 。
|
24
thinkIn 2021-07-15 10:14:25 +08:00 via iPhone
@lonewolfakela 我表述有误,不过可以看看用宏定义的 sizeof,虽然有限制,但是对理解指针很有好处。可以参看这个讨论 https://stackoverflow.com/questions/14171117/implementation-of-sizeof-operator
|