Arrays have fixed lengths that are known within the scope of their declarations. Nevertheless, it is possible and sometimes convenient to calculate array lengths. In particular, this can make code more flexible when the array length is determined automatically from an initializer:
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]);
However, in most contexts where an array appears in an expression, it is automatically converted to ("decays to") a pointer to its first element. The case where an array is the operand of the sizeof
operator is one of a small number of exceptions. The resulting pointer is not itself an array, and it does not carry any information about the length of the array from which it was derived. Therefore, if that length is needed in conjunction with the pointer, such as when the pointer is passed to a function, then it must be conveyed separately.
For example, suppose we want to write a function to return the last element of an array of int
. Continuing from the above, we might call it like so:
/* array will decay to a pointer, so the length must be passed separately */
int last = get_last(array, length);
The function could be implemented like this:
int get_last(int input[], size_t length) {
return input[length - 1];
}
Note in particular that although the declaration of parameter input
resembles that of an array, it in fact declares input
as a pointer (to int
). It is exactly equivalent to declaring input
as int *input
. The same would be true even if a dimension were given. This is possible because arrays cannot ever be actual arguments to functions (they decay to pointers when they appear in function call expressions), and it can be viewed as mnemonic.
It is a very common error to attempt to determine array size from a pointer, which cannot work. DO NOT DO THIS:
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 */
}
In fact, that particular error is so common that some compilers recognize it and warn about it. clang
, for instance, will emit the following warning:
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[])
^