3 ms·
C now has static array indices. For example void func(int arr[static 8]) {} imposes a limit on the size of the array that can be passed as an argument (you ca
by utopcell 10y ago
C now has static array indices.
For example
void func(int arr[static 8]) {}
imposes a limit on the size of the array that can be passed as an argument (you cannot pass an array of 7 or fewer elements.)
I'd suggest that to the author, but given the article, I fear it may give him a heart attack.
- sdegutis 10y agoWhat version of C is this in? And do modern implementations (clang, GCC) adhere to it (without extensions)?
- utopcell 10y agoIt is C99 so it has been part of the language for a very long time
- Vindicis 10y agoJust to add, from the N1256 draft of C99, 6.7.5.3: A declaration of a parameter as ‘‘array of type’’ shall be adjusted to ‘‘qualified pointer to type’’, where the type qualifiers (if any) are those specified within the [ and ] of the array type derivation. If the keyword static also appears within the [ and ] of the array type derivation, then for each call to the function, the value of the corresponding actual argument shall provide access to the first element of an array with at least as many elements as specified by the size expression.
- FreeFull 10y agoIt's a feature added in C99. Both clang and GCC do support it, assuming -std=c99 or later
- ThatGeoGuy 10y agoI know they're called static array indices, and they're called that because of the use of the keyword `static`, but they don't have to be compile time constant at all (and checks aren't performed at compile time, IIRC). You can have the following: void foo(size_t len, int arr[static len]); Which is really useful in asserting that you won't pass in the null pointer at runtime (so you can remove any `if (arr) {}` checks). Taken further, this exact method is what makes the restrict keyword usable in practice. One of the main problems of the restrict keyword is that you shouldn't be aliasing pointers. By ensuring that your passed-in array isn't actually a null pointer using the above syntax, you avoid one of the biggest problems of aliasing: passing in two null pointers. Consider: void foo1(size_t len1, restrict int* arr1, size_t len2, restrict int* arr2); vs void foo2(size_t len1, restrict int arr1[static len1], size_t len2, restrict int arr2[static len2]); The second is more verbose, but you have a stronger guarantee that this procedure won't be called with pointers aliased to NULL. The compiler can (and I believe in the case of GCC, will) take advantage of this.
- utopcell 10y agoChecks against constants are indeed compile-time.
- clarry 10y ago> Taken further, this exact method is what makes the restrict keyword usable in practice. One of the main problems of the restrict keyword is that you shouldn't be aliasing pointers. [..] one of the biggest problems of aliasing: passing in two null pointers You shouldn't be dereferencing NULL pointers. Aliasing them is perfectly fine. The non-aliasing requirements of restrict kick in only when you are actually accessing (and modifying!) the object referenced by an lvalue based on an expression of the restrict qualified pointer. So NULL pointers don't matter because first, they do not point to an object, and second, if you dereference them, you're already in UB land anyway. Correct code will not dereference NULL pointers, therefore the restrict qualification means absolutely nothing on code that opts to not try access anything through NULL pointers. EDIT: N1256 6.7.3.1p4 under Formal definition of restrict (emphasis mine): > During each execution of B, let L be any lvalue that has &L based on P. If L is used to access the value of the object X that it designates, and X is also modified (by any means), then the following requirements apply: T shall not be const-qualified. Every other lvalue used to access the value of X shall also have its address based on P. Every access that modifies X shall be considered also to modify P, for the purposes of this subclause. If P is assigned the value of a pointer expression E that is based on another restricted pointer object P2, associated with block B2, then either the execution of B2 shall begin before the execution of B, or the execution of B2 shall end prior to the assignment. If these requirements are not met, then the behavior is undefined.