当C数组作为函数参数传递时,为什么其sizeof()值会出现错误?

37

完整的示例:

#include <stdio.h>

void test(int arr[]) {
    int arrSize = (int)(sizeof(arr) / sizeof(arr[0]));
    printf("%d\n", arrSize); // 2 (wrong?!)
}

int main (int argc, const char * argv[]) {
    int point[3] = {50, 30, 12};

    int arrSize = (int)(sizeof(point) / sizeof(point[0]));
    printf("%d\n", arrSize); // 3 (correct :-) )

    test(point);

    return 0;
}

在将其传递给函数之前,sizeof可以给出正确的值。但是,在函数中对完全相同的数组执行完全相同的操作会导致奇怪的结果,其中缺少一个元素。为什么?

6个回答

52
在C语言中,当你将一个数组传递给函数时,该数组会衰变为指向其第一个元素的指针。当你在参数上使用sizeof时,你得到的是指针的大小,而不是数组本身的大小。
如果你需要函数知道数组的大小,你应该将其作为另一个参数传递:
void test(int arr[], size_t elems) {
   /* ... */
}

int main(int argc, const char * argv[]) {
   int point[3] = {50, 30, 12};
   /* ... */
   test(point, sizeof(point)/sizeof(point[0]));
   /* ... */
}

还要注意的是,因为采用了sizeof指针的方法,所以 sizeof(point)/sizeof(point[0]) 技巧仅适用于在堆栈上分配的数组,而不适用于动态分配的数组。


15

因为数组作为函数参数时会发生衰变,所以在32位和64位平台上,sizeof分别返回4和8。


6
此外,重要的是要理解 sizeof编译时计算。因此,在test()中传入不同的参数,期望获得不同的输出是没有意义的。在函数编译时,sizeof 计算已经完成。

3
因为只有数组指针被传递,所以当它被传递时,只有指向数组的指针实际上被传递了。
你的问题在C编程FAQ中也得到了回答。问题6.21。

挑剔一点:它是传递的数组第一个元素的指针。值相同,但类型不同。 - alk

2

因为在C、C++和Objective-C中,函数实际上不能有数组参数。它们只能有看起来像数组参数的参数,但它们并不是真正的数组参数。在你的例子中,

void test(int arr[])

编译器看到“有一个参数看起来像int数组”,并将该参数替换为“指向int的指针”。因此,您编写的函数与原始函数完全相同。
void test (int* arr)

因此,在函数内部使用 sizeof(arr) 将会返回一个“指向整型的指针”的大小。

0

如果你仔细看了这个例子,你会发现我没有直接使用sizeof来获取数组中元素的数量... sizeof应该告诉我为数组保留了多少内存...实际上,当元素的大小已知时,这应该与其中有多少元素相匹配。或者我漏掉了什么? - dontWatchMyProfile
我改正了。但是如上所述,指针要小心使用。它们告诉你它们的大小,而不是你所指向的类型的大小。 - PeterK

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接