为啥将 C-Array 传递给函数时 sizeof() 值错误? [复制]

Posted

技术标签:

【中文标题】为啥将 C-Array 传递给函数时 sizeof() 值错误? [复制]【英文标题】:Why does a C-Array have a wrong sizeof() value when it's passed to a function? [duplicate]为什么将 C-Array 传递给函数时 sizeof() 值错误? [复制] 【发布时间】:2011-02-26 09:05:01 【问题描述】:

完整示例:

#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 给了我正确的值。对函数中完全相同的数组执行完全相同的操作会产生奇怪的结果。少了一个元素。为什么?

【问题讨论】:

【参考方案1】:

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

void test(int arr[])

编译器看到“有一个参数看起来像一个 int 数组”,并将该参数替换为“指向 int 的指针”。所以你写的函数绝对百分百与

void test (int* arr)

因此,在函数 sizeof (arr) 内部会给你一个“指向 int 的指针”的大小。

【讨论】:

【参考方案2】:

此外,了解sizeof编译时 进行评估也很重要。既然是这种情况,根据传入的内容来期望 test() 中的不同输出是没有意义的。sizeof 计算是在编译函数时完成的。

【讨论】:

【参考方案3】:

当您将数组传递给 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]) 技巧不适用于动态分配的数组,仅适用于堆栈上分配的数组。

【讨论】:

【参考方案4】:

因为数组在作为函数参数传递时是指向指针的 decayed,所以 sizeof 分别为 32 位和 64 位平台提供 4 和 8。

【讨论】:

【参考方案5】:

因为 sizeof() 不会告诉你 C 中数组的大小。它做的事情完全不同。

sizeof C++ reference

【讨论】:

如果你仔细看过这个例子,你会发现我没有使用 sizeof 来直接获取数组中的元素个数... sizeof 应该告诉我有多少内存为数组保留......实际上,当元素的大小已知时,它应该与其中的元素数量相匹配。还是我错过了什么? 我的立场是正确的。但如上所述,要小心指针。他们告诉你它们的大小,而不是你指向的类型的大小。【参考方案6】:

因为,当它被传递时,实际上只有指向数组的指针被传递。

The C Programming FAQ 也回答了您的问题。问题 6.21。

【讨论】:

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

以上是关于为啥将 C-Array 传递给函数时 sizeof() 值错误? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

为啥通过 ParamArray 将数组元素传递给函数时,varpointer 会到达函数中?

为啥这个指针是 8 个字节?

为啥使用 DT_MODIFYSTRING 选项将副本传递给 DrawText 函数时,原始 CString 会被覆盖?

无法从创建它的方法外部访问 C-Array 元素

为啥将字符串传递给接受 LPSTR 的函数不起作用?

C:为啥你可以通过值传递(给函数)一个结构,而不是一个数组?