I just found out that this is illegal in C++ (but legal in C):
#include
#include
#define ARRAY_LENGTH(A) (sizeof(A) / sizeof
C++ doesn't have C's notion of "compatible type". In C, this is a perfectly valid redeclaration of a variable:
extern int (*a)[];
extern int (*a)[3];
In C, this is a perfectly valid redeclaration of the same function:
extern void f();
extern void f(int);
In C, this is implementation-specific, but typically a valid redeclaration of the same variable:
enum E { A, B, C };
extern enum E a;
extern unsigned int a;
C++ doesn't have any of that. In C++, types are either the same, or are different, and if they are different, then there is very little concern in how different they are.
Similarly,
int main() {
const char array[] = "Hello";
const char (*pointer)[] = &array;
}
is valid in C, but invalid in C++: array
, despite the []
, is declared as an array of length 6. pointer
is declared as a pointer to an array of unspecified length, which is a different type. There is no implicit conversion from const char (*)[6]
to const char (*)[]
.
Because of that, functions taking pointers to arrays of unspecified length are pretty much useless in C++, and almost certainly a mistake on the part of the programmer. If you start from a concrete array instance, you almost always have the size already, so you cannot take its address in order to pass it to your function, because you would have a type mismatch.
And there is no need for pointers to arrays of unspecified length in your example either: the normal way to write that in C, which happens to also be valid in C++, is
int accumulate(int n, int *array)
{
int i;
int sum = 0;
for (i = 0; i < n; ++i) {
sum += array[i];
}
return sum;
}
to be called as accumulate(ARRAY_LENGTH(a), a)
.
Dan Saks wrote about this in 1995, during the lead up to C++ standardisation:
The committees decided that functions such as this, that accept a pointer or reference to an array with unknown bound, complicate declaration matching and overload resolution rules in C++. The committees agreed that, since such functions have little utility and are fairly uncommon, it would be simplest to just ban them. Hence, the C++ draft now states:
If the type of a parameter includes a type of the form pointer to array of unknown bound of T or reference to array of unknown bound of T, the program is ill-formed.