数组长度

数组具有固定长度,这些长度在其声明范围内是已知的。然而,计算阵列长度是可能的并且有时是方便的。特别是,当从初始化程序自动确定数组长度时,这可以使代码更灵活:

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[])
                     ^