Funny thing about that n[static M] array checking syntax–it was even considered bad in 1999, when it was included:
"There was a unanimous vote that the feature is ugly, and a good consensus that its incorporation into the standard at the 11th hour was an unfortunate decision." - Raymond Mak (Canada C Working Group), https://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_205.htm
There are perhaps only 3 numbers: 0, 1, and lots. A fair argument might be made that 2 also exists, but for anything higher, you need to think about your abstraction.
Pointer to array is not only type-safe, it is also objectively correct and should have always been the syntax used when passing in the address of a known, fixed size array. This is all a artifact of C automatically decaying arrays to pointers in argument lists when a array argument should have always meant passing a array by value; then this syntax would have been the only way to pass in the address of a array and we would not have these warts. Automatic decaying is truly one of the worst actual design mistakes of the language (i.e. a error even when it was designed, not the failure to adopt new innovations).
And the reason why C has array-pointer decay is because that made it work more or less like B (which had to do it since it literally didn't have any type other than machine word).
That weird feeling when you realise that the people you hang out with form such a weird niche that something considered common knowledge among you is being described as "buried deep within the C standard".
What's noteworthy is that the compiler isn't required to generate a warning if the array is too small. That's just GCC being generous with its help. The official stance is that it's simply undefined behaviour to pass a pointer to an object which is too small (yes, only to pass, even if you don't access it).
That is all well. But thing_t is an array type which still decays to pointer.
It looks as if thing_t can be passed by value, but since it is an array, it sneakily isn't passed by value:
void catch_with_net(thing_t thing); // thing's type is actually "usnsigned char *"
// ...
unsigned char x[42]];
catch_with_net(x); // pointer to first element passed; type checks
Unfortunately you cannot use static in array typedefs, which really blows. So you have to have an extra constant to keep track of the array size in order to use it. If it worked on typedefs, you could just make the array parameter the appropriate type and derive the array's count with sizeof(array_type_t).
18 comments
[ 5.3 ms ] story [ 51.7 ms ] thread"There was a unanimous vote that the feature is ugly, and a good consensus that its incorporation into the standard at the 11th hour was an unfortunate decision." - Raymond Mak (Canada C Working Group), https://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_205.htm
There are perhaps only 3 numbers: 0, 1, and lots. A fair argument might be made that 2 also exists, but for anything higher, you need to think about your abstraction.
It is not limited to compile-time constants. Doesn't work in clang, sadly.
What's noteworthy is that the compiler isn't required to generate a warning if the array is too small. That's just GCC being generous with its help. The official stance is that it's simply undefined behaviour to pass a pointer to an object which is too small (yes, only to pass, even if you don't access it).
For reference: https://digitalmars.com/articles/C-biggest-mistake.html
https://clang.llvm.org/docs/AttributeReference.html#counted-...
The problem is that they are attractive for reducing repeated declarations:
That is all well. But thing_t is an array type which still decays to pointer.It looks as if thing_t can be passed by value, but since it is an array, it sneakily isn't passed by value:
Or are you just referring to the function where one defines it as apparently 'pass by value'?
https://developer.arm.com/community/arm-community-blogs/b/em...
You could just declare
and pass those around to get roughly the same effect.