sizeof 计算问题求解

2021-07-14 15:40:02 +08:00
 JQiue
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

2484 次点击
所在节点    C
26 条回复
ho121
2021-07-14 15:55:45 +08:00
数组传参后都是指针,指针大小在 32 位环境下是 4,64 位环境下是 8
JQiue
2021-07-14 15:58:35 +08:00
@ho121 这个我知道,但是为什么 sizeof 在主函数中却是计算数组的所有元素大小
qieqie
2021-07-14 15:59:15 +08:00
一个是指针一个是数组,第一个 arr 等效的是&arr[0]
ipwx
2021-07-14 16:16:34 +08:00
首先,指针和数组不等效。。。楼主你想当然地信仰了一个错误观点。



sizeof(int*) == 4
sizeof(int[5]) == 20
3dwelcome
2021-07-14 16:17:29 +08:00
@JQiue “但是为什么 sizeof 在主函数中却是计算数组的所有元素大小”

因为 C/C++是类型推导语言,但是函数参数传递中,会丢失原来的类型。

你在两个函数里,分别用 typeid(arr).name()打一下类型名称就知道了,两者不一样。
thinkIn
2021-07-14 16:37:42 +08:00
sizeof 一般是用 define 定义的,你可以看下原理,很简练
wudicgi
2021-07-14 16:45:13 +08:00
"arr 很显然和 arr[0]是等效的"

当然不是等效的,否则 sizeof(arr) / sizeof(arr[0]) 这种计算元素数量的方法还怎么工作
hanssx
2021-07-14 16:49:03 +08:00
@3dwelcome 是不是看下汇编代码会比较有帮助?

楼主你没发现类型变了嘛,实参和形参的类型实际上是不一样的,你说的等效,也需要加上取地址符,而且只是地址这个数值等效。一个变量是有类型和大小的。
lesismal
2021-07-14 17:04:26 +08:00
《 C 陷阱与缺陷》《 C 专家编程》《 C 和指针》了解一下
rshun
2021-07-14 17:06:12 +08:00
函数参数那个*arr 表示的是数组第一个元素,即 arr[0],所以你在函数内做 sizeof 的时候就是 4
你在 main 里面的做 sizeof,是数组的所有元素,所以是 4*5=20
echoechoin
2021-07-14 17:08:40 +08:00
数组传递到函数中会被转换为指针!!! 所以 sizeof (数组) != sizeof(指针)
ho121
2021-07-14 17:10:22 +08:00
@JQiue
主函数中,arr 依然是数组,所以 sizeof 的结果是数组大小。另一方面 arr 也可以作为表达式,它代表的是 arr 数组的首地址。

函数调用 foo(arr)中的 arr 是作为表达式出现的,所以是指针。sizeof arr 中的 arr 代表数组本身。
lesismal
2021-07-14 17:13:14 +08:00
国人写的印象中《 C 语言深度解剖》还不错,太久了,记不清了。还有本《狂人 C:程序员入门必备》我没看过,但是当初作者在论坛跟大家 PK 各种 C 问题,很多老伙计一块给提了不少勘误和意见,内容应该能靠谱些吧

刚还搜到一本日本人的《征服 C 指针》,也没读过,但是以前读过的一些日本作者的技术书籍,感觉都挺不错的
lesismal
2021-07-14 17:16:02 +08:00
多读几本好书就理解清楚了,C 的细节还挺多呢,这么零散着问,很难系统吸收知识点,建议猛读一下我推荐的那几本书
OliverDD
2021-07-14 17:52:14 +08:00
JQiue
2021-07-14 17:57:03 +08:00
@wudicgi 嗯嗯这个我写错了
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
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
}
agagega
2021-07-14 19:16:08 +08:00
C 的数组不是指针,只是某些时候可以相互转换
LnTrx
2021-07-14 19:29:59 +08:00
在函数里无论是写成数组还是指针,实际上都是指针,数组大小的信息已经丢失了

https://www.geeksforgeeks.org/why-c-treats-array-parameters-as-pointers/

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/789496

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX