5 ms·
Seems cool, but how is useful in practice? In 15 years I've never written a C function taking a fixed array size at all. I always write my functions with a dyna
by vortico 8y ago
Seems cool, but how is useful in practice? In 15 years I've never written a C function taking a fixed array size at all. I always write my functions with a dynamic size argument like
void foo(char *data, int len)
Perhaps cryptography functions with 256-bit outputs might be able to use this, but even when the array size is fixed, most crypto libraries (like OpenSSL) tend to have a size argument anyway, to encourage the caller to think about what they're doing, and for the library to check that 32 bytes are actually available, for example.
- kzrdude 8y agoyou can however use void foo(char data[static 0], int len) with 0 or 1 to signal at least zero/one elements are required (for example), and the pointer must be non-null.
- kbp 8y agoThe standard says "If the expression is a constant expression, it shall have a value greater than zero." Clang gives me a warning that "static 0" has no effect. NULL is valid as a pointer to a 0-length array, so that makes sense that it wouldn't function as a non-NULL assertion.
- Sir_Cmpwn 8y agoHere's one example of where I've used this: void wlr_matrix_multiply(float mat[static 9], const float a[static 9], const float b[static 9]);
- hoppelhase 8y agoAs this is valid, but only useful as documentation: void foo(const int n, const char data[n]) Is this also valid? void foo(const int n, const char data[static n])
- codys 8y agoThe `n` may be any assignment-expression, and as a result values like `n` are appear to be allowed by the standard. I've used this in code compiled with gcc and clang. Both accept this construct, but I'm not sure how effectively any compiler is able to use this information to emit warnings/errors.
- int_19h 8y agoIf you have ever written a function that accepts a pointer to a single value as an argument, with null pointer not being valid input, then declaring it as a static 1-element array should make things just a little bit better (mainly because the compiler can assume no null).
- jefftk 8y agoYou could define a macro NOTNULL for this, to make it clearer to readers. void foo(char bar[static 1]) vs void foo(NOTNULL(char* bar)) Though I'm not sure whether this can be expressed as a macro, since you need to remove the "*"?
- saagarjha 8y agoHow about this: #define NOTNULL void foo(NOTNULL char *bar) If you're using Objective-C, then nonnull is your friend.
- int_19h 8y agoThe point is to get [static 1] in the expansion of the macro, so that the compiler is aware too, not just the coder.
- saagarjha 8y agoAh. I was wondering why this was difficult; thanks for the clarification!
- 1over137 8y agoThe clang nullability annotations can be used in C/C++ as extensions: https://clang.llvm.org/docs/AttributeReference.html#nullability-attributes https://clang.llvm.org/docs/AttributeReference.html#nullabil... You could then conditionally define your NOTNULL using them or not. The compiler will then complain about incorrect usage.
- shaklee3 8y ago
- 1over137 8y agovoid SetColour (const double rgb[static 3])
- mannykannot 8y agoNice try, but a struct would be more appropriate.
- 1over137 8y agoSometimes, but not always. ex: a big piece of RGBRGBRGB memory that you iterate. ex: https://www.vtk.org/doc/nightly/html/classvtkProperty.html#a3a9495e8f26e82d3da87a1c949a85751 https://www.vtk.org/doc/nightly/html/classvtkProperty.html#a...
- DSMan195276 8y agoI would agree. IMO, I would argue that if you are in that situation, you should just wrap the array in a `struct`. It will work the same way, but now nobody can get the size wrong - the `struct` will always have an array of the correct length inside it. And as a bonus you can give it a good name.
- 0x09 8y agoI like using pointer-to-array types for this purpose as (like an array in struct) the array's length is encoded in the type, and thus likewise allows the compiler to warn if an incompatible array is provided. e.g. void f(char (*n)[255]); char array[6]; f(&array); warns of "incompatible pointer types passing 'char (* )[6]' to parameter of type 'char (* )[255]'" This won't produce a diagnostic for f(NULL) like "static" does, but does have two properties that might be considered benefits: 1) The length is exact rather than a minimum. 2) The type of "* n" is still char[255], whereas a char[static 255] parameter is still a decayed pointer-to-char. Thus with the former sizeof(* n) behaves as expected inside of "f", yielding 255. These are true of the array-in-struct method as well.
- j1elo 8y agoThis is a fantastic technique that didn't occur to me for an embedded project that I was developing in C and where passing arrays of known size was a frequent thing. Also it was desirable to save space by avoiding the padding that a "array+size" struct would contain. Thanks for commenting this.
- 1over137 8y agoBut remember structure padding, which the compiler is free to add in the middle (and end) of a struct (though there are pragmas and/or attributes to pack structs). IOW, an array and a struct are not necessarily the same in memory.
- rocqua 8y agoThe array in a struct is still going to be continuous in memory. All you might change is allignment.
- mannykannot 8y agoNot only do the opportunities to use it seem to be limited, but the opportunities for the compiler to statically check that the constraint is respected seem limited, both in the case of the caller and in the implementation of the function.
- int0x80 8y agoThis is not primary about static checking. This is mostly a guarantee to the implementation so it has information at the target function so it can generate better code without having to resort to derivations or complex data flows (to optimize, basically).
- cjhanks 8y agoWhen doing geometry, it is common to pass around double[3] or double[3][3] types.
- nwmcsween 8y agoYou didn't read the article it seems static in this context doesn't mean a fixed array size it means at least as many as indicated. Take for example strlen(const char *src) could be strlen(const char src[static 1])
- Mikhail_Edoshin 8y agoSometimes there are fixed arrays. E.g. an MD5 hash is 16 bytes, classic Mac OS file/creator types were 4 bytes, and so on.
- jjgreen 8y agoHere's an example of "use in anger", https://gitlab.com/jjg/lcrp/blob/master/lcrp.c#L159 https://gitlab.com/jjg/lcrp/blob/master/lcrp.c#L159 -- the algorithm used needs the array to have at least 3 elements, generally there will be more. It seems useful that there is a mechanism to warn the future me that this limit should be observed.