为什么被调函数内部不能用 sizeof(arr) / size(arr[0]) 计算数组长度?

简介: 该文解答了一个关于C语言的疑问,涉及64位RedPandaDevc++编译器。示例代码展示了不能通过`sizeof(arr)/sizeof(arr[0])`在函数中计算数组长度的问题,因为`arr`在函数中作为指针传递,`sizeof(arr)`返回指针大小(可能是4或8字节),而非数组长度。因此,代码在函数内输出可能为2。而在`main()`函数中,`sizeof(arr)`会计算整个数组大小,正确返回数组长度。文章强调了数组名在不同上下文中的差异以及`sizeof`操作符的使用注意事项。

本文是对该C语言小困惑的一个解答。


本文测试采用的编译器为64位的 RedPandaDevc++编译器。



我们给出如下测试代码:


int Test(int arr[]){
  return sizeof(arr)/sizeof(arr[0]);
}
 
int main(){
  int arr[10] = {1,2,3,4,5,6,7,8,9,10};
  int ret = Test(arr);
  
  printf("%d",ret);
}


提出这个困惑的朋友们都知道,这段代码是不可能实现“计算数组长度”这个功能的。


那么它的输出结果可能是多少呢?



在64位编译器中,显示的结果为 2


解答:


∵ 数组名作为函数实参传递时,传递的实际是其首元素的地址。接收的一方,接收的实际是指针。


上述代码中, int ret = Test(arr); 这当中的arr是数组的首元素地址,即&arr[0]


int Test(int arr[]),int arr[]等价于int* arr,用作接收的形参实际是指针。


∴ 在函数中,sizeof(arr),arr虽然和数组名长得一样,但其实并不是数组名,而是指针变量(相当于 int* p,sizeof(p))


∴ 指针变量的长度是4字节或8字节,sizeof(指针变量)自然就输出4或8


//测试一下指针变量的长度
 
int main(){
  int a;
  int* p = &a;
  
  printf("%zu",sizeof(p));
  return 0;
}



所以同理,在被调函数内部,由于arr也是指针,sizeof(arr)并不会输出数组的长度,而是指针变量的长度,也会输出4或者8.


有些同学可能会纠结于,数组名不就代表首元素的地址吗?是的,数组名在大部分情况下代表数组首元素地址(例外情况下面说),但和本题是两码事。


虽然首元素的地址和数组的地址是同一个,但是不影响一个是指针一个是数组名。记住被调函数中没有整个数组,只有一个指针即可。


回到 sizeof(arr) / size(arr[0]) 这一表达式。sizeof(arr)值为8(或4),arr[0]为普通的int类型变量,sizeof(arr[0])的值和sizeof(int)的值相等,都是4 (int类型的长度也是有可能为8的,而我的编译器是4)。因而整个表达式的值是  8/4 ,输出的结果自然是2了。


但在main函数中,sizeof(arr)是会计算整个数组所占的内存空间大小。因为在sizeof中,arr并不表示数组首元素的地址,而表示整个数组。这就是数组名不表示数组首元素地址的例外情况。


可以作为结论记住:sizeof(数组名)与&数组名,正是数组名不表示数组首元素地址的例外情况。


(&数组名,取的是整个数组的地址。上述代码中的&arr+1 ,地址增加了40(个存储单元),而arr+1 和 &arr[0]+1 相等,地址增加了 4 )


int main(){
  int arr[10] = {1,2,3,4,5,6,7,8,9,10};
  //int ret = Test(arr);
  printf("%zu",sizeof(arr));    //计算出arr数组的总空间为40
}


int main(){
  int arr[10] = {1,2,3,4,5,6,7,8,9,10};
  int ret = sizeof(arr)/sizeof(arr[0]);
 
  printf("%d",ret);    //计算出该数组的长度为10
}


考点:数组作为函数参数的使用、sizeof 操作符的使用

相关文章
|
4月前
|
Python
使用array()函数创建数组
使用array()函数创建数组。
79 3
为数组 arr 中的每个元素求二次方。不要直接修改数组 arr,结果返回新的数组
为数组 arr 中的每个元素求二次方。不要直接修改数组 arr,结果返回新的数组
|
2月前
|
JavaScript
Js,定义数组的方法,let 数组名 = [数据1,数据2,........,数据n],取值方法,数组名[x],arr[0],let sum sum = sum + arr[0],求和的写法,平均值
Js,定义数组的方法,let 数组名 = [数据1,数据2,........,数据n],取值方法,数组名[x],arr[0],let sum sum = sum + arr[0],求和的写法,平均值
数组求最大值和最小值的方法,数组写最大值和最小值的三元写法,数组取最小值,如何在数组中添加最后一个值,arr.push()添加数组放到后面,arr.unshift(‘red‘)添加的放到前面
数组求最大值和最小值的方法,数组写最大值和最小值的三元写法,数组取最小值,如何在数组中添加最后一个值,arr.push()添加数组放到后面,arr.unshift(‘red‘)添加的放到前面
|
4月前
|
C语言 C++
C++ sizeof()运算符的参数为指针和数组的值为什么不同
C++或C语言中,都可以使用sizeof()运算符来计算数组的字节大小,除此之外,在C++和C语言中,都可以使用一个指向数组第一个元素的内存地址的指针来引用数组,因此,如果要计算数组的字节大小,或长度,传递数组本身或传递指向数组的指针给sizeof()运算符似乎都是可以的,实际上则不然,
64 5
|
4月前
|
存储 算法 Java
实现一个函数 splice(int[] a, int b[], int n, int m) 将数组 b 插入到数组 a 的第 n 个位置上去,并将其后面的元素后移 m 个位置,同时更新数组 a 的长度
实现一个函数 splice(int[] a, int b[], int n, int m) 将数组 b 插入到数组 a 的第 n 个位置上去,并将其后面的元素后移 m 个位置,同时更新数组 a 的长度
34 0
sizeof的返回值类型:size_t
sizeof返回值类型是 size_t ,size_t 是无符号整数类型
227 0
|
C语言
详解sizeof、strlen、指针和数组等组合题
详解sizeof、strlen、指针和数组等组合题
|
C语言
虎头虎脑的sizeof、strlen、数组长度、数组中元素个数和字符串长度
虎头虎脑的sizeof、strlen、数组长度、数组中元素个数和字符串长度