我想得到一个数组的长度,比如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
函数以获得数组的长度?
答案 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
映射回它指向的数组。