I am convinced there is some kind of long-term drinking game going on in the C standards committee to see how many different uses they can come up with for the word "static".
They don't really have a choice, do they? If you want to add features you can either: 1) make a new reserve word, possibly breaking existing code 2) reuse a reserve word in a new context.
This works with pointers in both C and C++. int (*foo)[10] is a pointer to an array of exactly 10 elements. The novel thing being pointed out in the OP is the "10 or more" aspect.
I can confirm. Perhaps this is a bug? As per the C99 standard [Clause 6.7.5.3: Function Declarators, point 7]:
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.
Since that's a 'shall' declaration, shouldn't it at least throw out a warning?
Can someone recommend a resource that talks about some interesting C stuff similar to this? I've looked at "Expert C Programming: Deep C Secrets" but found it a bit outdated. And the C standard is a bit dry :-).
You might look at 21st Century C: C Tips from the New School by Ben Klemens. It's very new (November 2012), and has some really nice stuff in it.
It's getting mixed reviews, but I really found it useful (even if I, like others, disagree with some of his tips). It's particularly good at sorting out what you can do in C99 and C11.
[edit: He has a really useful section on sorting out the different meanings of "static" in C, though I don't recall this being one of them.]
The International Obfuscated C Code Contest (http://ioccc.org/) has some real gems.
Compiling another language to C is good way to learn a lot about C's nooks and crannies.
You could also look at C coding standards such as the MISRA guidelines. While many things they complain about should be obvious, there will inevitably be some really obscure things they urge you not to try.
Unfortunately, gcc does not warn. I can pass a NULL pointer and arrays that are too small. But on the other hand, there is very little use, because arrays usually contain an arbitrary number of elements. This might be useful for matrices and vectors, but then I would rather wrap them in a struct anyway.
This is one of the things that attracts me to Go (and developing tools for working with it, which requires parsing the language, etc.). It's much easier to keep the entire language spec in your working memory, because it all fits in http://golang.org/ref/spec.
What makes me wary of using these uncommon constructs is that someone editing code later may make a change based on a superficial understanding (and break the build)
Why do many features added to C after the first standard have to be quirky and slightly incompatible (with C++, with existing implementations, etc.) like this?
Other examples are inline (different from C++, makes use of weird combinations with static and extern) and tgmath (compiler magic inaccessible to user-defined functions until C11).
They also seem to __barely__ improve the language without ever being "cool" or "interesting".
At least C++ has some standard data structures...
PS: Even Python has binary literals, while they were deemed "not useful enough" for C.
6.7.5.3 point 7: “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.”
Interesting, but the one comment I haven't seen yet on this thread is 'Why is this useful enough to be a compiler feature?'. I think this is especially relevant with a relatively slim language like C.
In the rare cases you need to do this sort of check why not just write a simple sizeof test?
The compiler doesn't pass any size information when you pass an array into a function. The function just gets a pointer. If you take the sizeof the array, you'll get the size of a pointer on your system:
[eric@rangely foo]$ cat foo.c
#include <stdio.h>
int test (int arr[10])
{
printf ("%lu\n", sizeof (arr));
return 0;
}
int main (int argc, char *argv[])
{
int arr[5];
test (arr);
return 0;
}
As another poster said, the compiler can't know inside the function body the size of the array passed if you just use sizeof.
More to a style/safety point, if I ever see a function that expects an array and doesn't also take the size of that array as another parameter, that's a bug waiting to happen.
Especially in this case since this feature seems to only throw a warning on recent versions of clang, and more or less nothing else.
Wouldn't you need to put your sizeof test outside of every call to your function? Inside the function it would only know the declared parameter's type, so it would have no idea what sized array you actually passed.
Using 'static' in this way compiles with both Oracle Studio 12 and IBM xlc 11, but neither exhibit the behavior that gcc is shown to have in the article. Passing in both NULL as well as an array of shorter length work just fine with no warning/error from the compiler.
According to section 6.7.5.2p1 of C99: “If the expression is a constant expression, it shall have a value greater than zero.”
The “expression” here refers to an expression in between [] in an array declaration; so the declaration of size 0 is a constraint violation and requires a diagnostic. You can get gcc and clang to issue a relevant diagnostic with “-std=c99 -pedantic”.
A whiff of C++ would be fine, as long as they don't take enough to make people think they have to pick a subset of C. One of C's strengths compared to C++ is that C is one language with a small number of dark corners, not multiple languages trying to share a single standards document.
[+] [-] tptacek|13 years ago|reply
[+] [-] matthavener|13 years ago|reply
[+] [-] bunderbunder|13 years ago|reply
[+] [-] unimpressive|13 years ago|reply
— Tom Duff
Not exactly the same situation, considering that compilers work.
[+] [-] Evbn|13 years ago|reply
[+] [-] matthavener|13 years ago|reply
You can also get the size at compile time:
I've used the above for something like this:[+] [-] pyrtsa|13 years ago|reply
[+] [-] chc|13 years ago|reply
[+] [-] Nav_Panel|13 years ago|reply
flags: -g -Wall -Wextra -std=c99 -pedantic
The following code compiles and runs (for me at least) with no errors. Tried with both stack and heap allocated arrays of various sizes.
[+] [-] ambrop7|13 years ago|reply
[+] [-] jrajav|13 years ago|reply
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.
Since that's a 'shall' declaration, shouldn't it at least throw out a warning?
[+] [-] onedognight|13 years ago|reply
This is not a reason to avoid the construct, but as yet gcc[1] doesn't optimize it either.
[1] http://gcc.gnu.org/c99status.html
[+] [-] niggler|13 years ago|reply
[+] [-] adamnemecek|13 years ago|reply
[+] [-] sramsay|13 years ago|reply
It's getting mixed reviews, but I really found it useful (even if I, like others, disagree with some of his tips). It's particularly good at sorting out what you can do in C99 and C11.
[edit: He has a really useful section on sorting out the different meanings of "static" in C, though I don't recall this being one of them.]
[+] [-] silentbicycle|13 years ago|reply
Compiling another language to C is good way to learn a lot about C's nooks and crannies.
You could also look at C coding standards such as the MISRA guidelines. While many things they complain about should be obvious, there will inevitably be some really obscure things they urge you not to try.
[+] [-] matthiasv|13 years ago|reply
[+] [-] nathell|13 years ago|reply
[+] [-] shurcooL|13 years ago|reply
[+] [-] niggler|13 years ago|reply
[+] [-] unknown|13 years ago|reply
[deleted]
[+] [-] vvhn|13 years ago|reply
[+] [-] PySlice|13 years ago|reply
Other examples are inline (different from C++, makes use of weird combinations with static and extern) and tgmath (compiler magic inaccessible to user-defined functions until C11).
They also seem to __barely__ improve the language without ever being "cool" or "interesting".
At least C++ has some standard data structures...
PS: Even Python has binary literals, while they were deemed "not useful enough" for C.
[+] [-] jmaygarden|13 years ago|reply
I also ran across this construct in a quick search [1]:
[1] http://stackoverflow.com/questions/3693429/c-parameter-array...[+] [-] ehamberg|13 years ago|reply
6.7.5.3 point 7: “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.”
[+] [-] cedricd|13 years ago|reply
In the rare cases you need to do this sort of check why not just write a simple sizeof test?
[+] [-] mauvehaus|13 years ago|reply
[eric@rangely foo]$ cat foo.c
[eric@rangely foo]$ gcc foo.c -Wall -o foo && ./foo8
(EDIT: fixed formatting)
[+] [-] kelnos|13 years ago|reply
More to a style/safety point, if I ever see a function that expects an array and doesn't also take the size of that array as another parameter, that's a bug waiting to happen.
Especially in this case since this feature seems to only throw a warning on recent versions of clang, and more or less nothing else.
[+] [-] corysama|13 years ago|reply
[+] [-] apaprocki|13 years ago|reply
So, YMMV.
[+] [-] yxhuvud|13 years ago|reply
What happen if you do
void bar(int fooArray[static 0]) {} ?
Is NULL allowed?
[+] [-] ehamberg|13 years ago|reply
[+] [-] quasive|13 years ago|reply
The “expression” here refers to an expression in between [] in an array declaration; so the declaration of size 0 is a constraint violation and requires a diagnostic. You can get gcc and clang to issue a relevant diagnostic with “-std=c99 -pedantic”.
[+] [-] unknown|13 years ago|reply
[deleted]
[+] [-] FlawedDesign|13 years ago|reply
[+] [-] galaktor|13 years ago|reply
"The size of an array is part of its type. The types [10]int and [20]int are distinct."
[1] http://golang.org/doc/effective_go.html#arrays
[+] [-] unknown|13 years ago|reply
[deleted]
[+] [-] derleth|13 years ago|reply
[+] [-] huhsamovar|13 years ago|reply