数组长度
数组具有固定长度,这些长度在其声明范围内是已知的。然而,计算阵列长度是可能的并且有时是方便的。特别是,当从初始化程序自动确定数组长度时,这可以使代码更灵活:
int array[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
/* size of `array` in bytes */
size_t size = sizeof(array);
/* number of elements in `array` */
size_t length = sizeof(array) / sizeof(array[0]);
但是,在表达式中出现数组的大多数上下文中,它会自动转换为(衰减到)指向其第一个元素的指针。数组是 sizeof
运算符的操作数的情况是少数例外之一。结果指针本身不是一个数组,它不携带有关从中派生它的数组长度的任何信息。因此,如果需要与指针一起使用该长度,例如当指针传递给函数时,则必须单独传送它。
例如,假设我们要编写一个函数来返回 int
数组的最后一个元素。从上面继续,我们可以这样称呼它:
/* array will decay to a pointer, so the length must be passed separately */
int last = get_last(array, length);
该功能可以像这样实现:
int get_last(int input[], size_t length) {
return input[length - 1];
}
特别要注意的是,虽然参数 input
的声明类似于数组的声明,但它实际上将 input
声明为指针 (对于 int
)。它完全相当于将 input
声明为 int *input
。即使给出了维度,情况也是如此。这是可能的,因为数组不能成为函数的实际参数(它们在函数调用表达式中出现时会衰减为指针),并且它可以被视为助记符。
尝试从指针确定数组大小是一个非常常见的错误,这不起作用。不要这样做:
int BAD_get_last(int input[]) {
/* INCORRECTLY COMPUTES THE LENGTH OF THE ARRAY INTO WHICH input POINTS: */
size_t length = sizeof(input) / sizeof(input[0]));
return input[length - 1]; /* Oops -- not the droid we are looking for */
}
事实上,这个特定的错误是如此常见,以至于一些编译器认识到它并对此发出警告。例如,clang
会发出以下警告:
warning: sizeof on array function parameter will return size of 'int *' instead of 'int []' [-Wsizeof-array-argument]
int length = sizeof(input) / sizeof(input[0]);
^
note: declared here
int BAD_get_last(int input[])
^