- 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).
- 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).
- 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).
- Better option: just wrap it in a unique struct.
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.
- GCC also has an extension to support references to other parameters of the function:
#include <stddef.h>
void foo(size_t n, int b[static n]);
https://godbolt.org/z/c4o7hGaG1It is not limited to compile-time constants. Doesn't work in clang, sadly.
- Excited to for Walter to drop by and extol the virtues of fat pointers :-)
For reference: https://digitalmars.com/articles/C-biggest-mistake.html
- But only for constant size arrays.
You could just declare
struct Nonce {
char nonce_data[SIZE_OF_NONCE];
}
and pass those around to get roughly the same effect.
by aaaashley
1 subcomments
- 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
- The pointer-to-array solution is okay, with the caveat that pointer-to-array typedefs should be avoided.
The problem is that they are attractive for reducing repeated declarations:
typedef unsigned char thing_t[THING_SIZE];
struct red_box_with_a_hook {
thing_t thing1, thing2;
}
void shake_hands_with(thing_t *thing);
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
by anonymousiam
1 subcomments
- This would not be the first time that the "static" keyword in C was reused for something "new" (relative to the original K&R pre-ANSI C).
https://developer.arm.com/community/arm-community-blogs/b/em...
- on a similar note, there are also these field attributes that are very helpful for catching similar issues:
https://clang.llvm.org/docs/AttributeReference.html#counted-...
- Anyone know if there's a flag to tell clang to treat `void fn(int array[N])` as if it was `void fn(int array[static N])`?