19

我想得到一个数组的长度,比如说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)in 函数length返回的指针大小为array? 但在功能main上,它是有效的。

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

4

8 回答 8

26

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

int length(int array[]);

相当于

int length(int *array);

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

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

于 2012-07-23T23:51:46.777 回答
6

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

于 2012-07-23T23:49:17.590 回答
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'
于 2012-07-24T01:31:29.807 回答
3

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

于 2012-07-23T23:47:25.647 回答
2

C 不使用变量存储有关数组大小的运行时元数据。您必须自己将其存储在某个地方。

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

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

于 2012-07-23T23:47:01.980 回答
2

如果您想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在这种情况下,操作员按您希望的方式工作。

于 2012-07-23T23:57:24.140 回答
0

因为里面的可变数组长度和外面的不一样。您必须将 sizeof(array) / sizeof(int) 保留在 main 函数中。

于 2012-07-23T23:47:31.707 回答
0

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

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

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

请注意,这适用于静态分配的数组,并且仅在使用原始数组调用时(使用指向数组的指针时不起作用)。这是因为当您编写指向数组的指针sizeof(x)where时,编译器会按字面意思解释它。xx评估sizeof.

于 2012-07-23T23:51:41.327 回答