为什么sizeof(param_array)是指针的大小?

时间:2012-07-23 23:44:54

标签: c

我想得到一个数组的长度,比如int array[] = {1, 2, 3, 4}。我使用sizeof来做到这一点。

int length(int array[])
{
     return sizeof(array) / sizeof(int);
}

int main()
{
    int array[] = {1, 2, 3, 4};
    printf("%d\n", length(array)); // print 1
    printf("%d\n", sizeof(array) / sizeof(int)); // print 4
}

那么,为什么函数sizeof(array)中的length返回指针大小array?但是在函数main中,它可以工作。

而且,我应该如何修改length函数以获得数组的长度?

8 个答案:

答案 0 :(得分:21)

一个特殊的C规则说,对于函数参数,数组类型调整到指针类型。这意味着:

int length(int array[]);

相当于

int length(int *array);

因此,当您计算sizeof数组时,实际上是在计算指针的大小。

  

(C99,6.7.5.3p7)“参数声明为”数组类型“应调整为”限定类型的指针“,其中类型限定符           (如果有的话)是在数组类型派生的[和]中指定的那些。“

答案 1 :(得分:5)

将数组传递给函数时,数组会衰减为指针。

答案 2 :(得分:5)

正如其他回答者所指出的那样,声明采用数组的函数的编译方式与采用指针的方式相同。

我看过你做长度方法的最常见的方法是使用#define,但如果你使用模板玩技巧,你可以让你的功能发挥作用。

template <size_t _Size> inline int length(int(& array)[_Size])
{
    //return sizeof(array) / sizeof(int);
    return _Size;
};

int array[] = {1, 2, 3, 4};
printf("%d\n", length(array)); // print 4

使用长度为4的数组,这将被编译为一个采用长度为4的数组的方法,并返回一个静态4.这样做的另一个好处是,如果你尝试传递一个不是数组的东西,编译器会给出错误,而#define方法则不会。

int* foo = array;
printf("%d\n", length(foo)); 
    // error C2784: 'int length(int (&)[_Size])' : could not deduce template
    //     argument for 'int (&)[_Size]' from 'int *'
    // test.cpp(56) : see declaration of 'length'

答案 3 :(得分:3)

在主程序中,编译器知道数组的长度。在子程序中,它没有。特别地,在子例程中,类型int[]的参数与类型int *的参数相同。另一方面,在主程序中,array的类型为int[4]。 (您可以通过尝试将另一个值分配给array中的main来进行测试。编译器会抱怨。)

答案 4 :(得分:2)

C不会存储有关变量的数组大小的运行时元数据。你必须把它存放在某个地方。

在方法 length 的上下文中, int [] 类型的变量只是指向内存块的指针。这就是为什么大小与系统上任何其他指针的大小相同。

sizeof 在编译时访问数组时(如在 main 函数中),它将返回数组占用的字节数。

答案 5 :(得分:1)

如果希望length知道传入数组的真实大小,那么必须传递这些信息,正如大家所说的那样。但它可以通过内置的信息接收对数组的引用:

int length(int n, int (* array)[n])
{
     return sizeof(*array) / sizeof(int);
}

int main()
{
    int array[] = {1, 2, 3, 4};
    printf("%d\n", length(4, &array)); // print 1
    printf("%d\n", sizeof(array) / sizeof(int)); // print 4
}

我不知道你实际上有什么好处,因为首先已经提供了尺寸。但是你可以看到sizeof运算符在这种情况下可以正常工作。

答案 6 :(得分:0)

因为变量数组内部长度与外部变量数组不同。你必须在main函数中保持sizeof(array)/ sizeof(int)。

答案 7 :(得分:0)

要修改代码以便length可以获取数组的长度,请将其转换为宏:

#define length(x) (sizeof(x)/sizeof(*x))

对于您的代码示例,这将按预期运行。

请注意,这将在静态分配的数组上工作,并且仅在使用原始数组调用时(使用指向数组的指针时不起作用)。这是因为当你编写sizeof(x) x是指向数组的指针时,编译器会按字面解释它。在评估x之前,它没有任何方法将sizeof映射回它指向的数组。