What is the purpose of static keyword in array parameter of function like "char s[static 10]"?
Asked Answered
W

1

188

While browsing some source code I came across a function like this:

void someFunction(char someArray[static 100])
{
    // do something cool here
}

With some experimentation it appears other qualifiers may appear there too:

void someFunction(char someArray[const])
{
    // do something cool here
}

It appears that qualifiers are only allowed inside the [ ] when the array is declared as a parameter of a function. What do these do? Why is it different for function parameters?

Wacky answered 7/8, 2010 at 11:58 Comment(0)
L
164

The first declaration tells the compiler that someArray is at least 100 elements long. This can be used for optimizations. For example, it also means that someArray is never NULL.

Note that the C Standard does not require the compiler to diagnose when a call to the function does not meet these requirements (i.e., it is silent undefined behaviour).

The second declaration simply declares someArray (not someArray's elements!) as const, i.e., you can not write someArray=someOtherArray. It is the same as if the parameter were char * const someArray.

This syntax is only usable within the innermost [] of an array declarator in a function parameter list; it would not make sense in other contexts.

The Standard text, which covers both of the above cases, is in C11 6.7.6.3/7 (was 6.7.5.3/7 in C99):

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.

Leaseholder answered 7/8, 2010 at 12:10 Comment(19)
On this topic: I wonder if it should be considered preferable to use int foo(struct bar [static 1]); instead of int foo(struct bar *); as the signature for functions which do not accept NULL pointers. (I know gcc has an alternate nonstandard syntax to flag such functions so that the compiler can give warnings..)Bluebell
I've just checked gcc and clang and neither assume that someArray is always non null when I ask them to compare against 0. Also I struggle to find the exact clause in C99 which defines it. There's a note in 6.7.5.3-21 which mentions the intended meaning and that's it. I doubt that we can rely on this. Furthermore, all this is not part of the function signature, so there not much that we enforce through it.Leaseholder
That link appears to have rotten away, is this what it was pointing to? pic.dhe.ibm.com/infocenter/zos/v1r12/…Smelser
If I do func(int a[static 4][6]) the static can only be declared within the first brackets. What if I do this func(int (*a)[static 6]) what will this do? Allow me to prefetch the first 6 values of the first row? And finally what about func(int *a[static 6])?Clothbound
@NordicMainframe: It's been some time, but the current version of clang now correctly warns when you attempt to pass a known-NULL argument to a function with a [static 1] parameter declaration.Wacky
Can anyone provide a minimal example of an optimization that could be or is done by compilers when static is present but not without?Sibship
@CiroSantilli巴拿馬文件六四事件法轮功 if (!someArray) { somecode... } could be removedPiteous
@Wacky That is certainly not intended or guaranteed by the standard. So this way you are relaying on specific implementation behavior which may not be supported by different compilers. And that's logical by the fact that int foo(struct bar *) and int foo(struct bar[static 1]) have the exact same type.Statecraft
@Nordic Mainframe You are incorrect - char someArray[const] is not the same as char (* const someArray)[]. No-matter the new extension added, still all parameters declared as "array of type" are adjusted to "pointer to type". Which means that someArray if of type char *const instead.Statecraft
@CisNOTthatGOODbutISOisTHATBAD The compiler is allowed to use the additional information to perform additional diagnosis (for example, report if a null pointer is passed, as R.. suggests). Can you clarify what you mean in that commentPiteous
@CisNOTthatGOODbutISOisTHATBAD sorry, that char (* const someArray)[] was my edit. Will fixPiteous
@CisNOTthatGOODbutISOisTHATBAD: I know that issuing a diagnostic is not required by the standard. There are lots of warnings (or diagnostics if you prefer) issued by compilers that are not required by the standard. What's your point?Wacky
My point is to not rely on unintended features as at certain point they may betray you. It's ok I guess for the compiler to issue a warning when it sees obvious violation but you mustn't rely on this behavior in the case. Image a scenario where only your function declaration is visible and you have missed to include the static specifier inside the array parameter declarator in it (which you have supposedly done in its definition later).Statecraft
Maybe if the compiler is smart enough it could save you from this situation either (warning your later in the function definition) but what if the function definition isn't available - the static keyword inside the array declarator isn't required to be part of the function type! - you won't get a nice warning then, your code will silently compile and it'll possibly not work correctly after if you were relaying on such warnings to test it.Statecraft
... shall provide access to the first element of an array with at least as many elements as specified by the size expression. So if I write void someFunction(char someArray[static 100]), shouldn't someArray be guaranteed to gave at least 1 + 100 = 101 elements?Shelashelagh
@Shelashelagh Unfortunately not. char someArray[static 100] is still an array of 100 elements, whose first element is someArray[0] and whose last element is someArray[99]. Your confusion may have arisen from the "provide access to" language, possibly inspired by the confusion of arrays and pointers (not quite equivalence, as seen elsewhere on this site): someArray[0] == *(someArray + 0) == *someArray.Rentsch
The second declaration simply declares someArray (not someArray's elements!) as const, i.e. you can not write someArray=someOtherArray -- could you ever write that, e.g. foo(char a[]){...a=b;...}?Loophole
What if a library header that I need to include in a C++ source file declares arrays using the static qualifier? Is this allowed by the C++ standard or a gnu extension?Enfeeble
@Loophole Yes, the a parameter is actually a pointer.Deduction

© 2022 - 2024 — McMap. All rights reserved.