C 为什么sizeof(param_数组)是指针的大小?

C 为什么sizeof(param_数组)是指针的大小?,c,C,我想得到数组的长度,比如说intarray[]={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) / sizeo

我想得到数组的长度,比如说
intarray[]={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
}
那么,为什么函数
length
中的
sizeof(array)
返回
array
的指针大小呢?但在函数
main
中,它可以工作


还有,我应该如何修改
length
函数来获取数组的长度?

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

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


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

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

因为变量数组内部长度与外部长度不同。您必须将sizeof(数组)/sizeof(int)保留在主函数中。

当您将数组传递到函数中时,数组将衰减为指针。

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

#define length(x) (sizeof(x)/sizeof(*x))
对于您的代码示例,这将按照您的预期进行


请注意,这仅适用于静态分配的数组,并且仅在使用原始数组调用时有效(使用指向数组的指针时无效)。这是因为当您编写
sizeof(x)
时,
x
是指向数组的指针,编译器会逐字解释它。在计算
sizeof
之前,它没有任何方法将
x
映射回它所指向的数组。一个特殊的C规则说,对于函数参数,数组类型调整为指针类型。这意味着:

int-length(int-array[])

相当于

int长度(int*数组)

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

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


如果您希望
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
运算符按您所希望的方式工作。

正如其他回答者所指出的,声明接受数组的函数的编译方式与接受指针的编译方式相同

我见过的最常用的长度方法是使用#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

是的,我知道这是一个C++问题,但是它也包含了关于C的非常有用的信息:“类型INT[]的变量只是指向内存块的指针”——在一般情况下这是不正确的。
int[]
类型的变量是一个内存块。它不是指针。
int[]
代表指针的唯一上下文是函数参数声明,这是一个特例。澄清了它是方法length()上下文中的指针。谢谢你指出这一点……这意味着你不能重写
length()
,以按你的意愿工作-如果一个函数需要知道数组的大小,它需要作为一个单独的参数传递给该函数。@caf我同意你的意见。对于其他信息,这样做是有意义的,尤其是在带有r0、r1、r2、r3 32位寄存器的ARM处理器上。因此,可以在r0中传递指针,而不必使用堆栈。啊,非常正确。哦,好吧,也许他会觉得它很有用。
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'