3

I saw following little complicated function definition.

void foo(double A[static 10]) {
   double B[10];    
}

Is it valid C & C++ code? Is it new syntax introduced by C99 or C++ standard? What is the purpose of it? When should I use it? What is the need for this?

Pascal Cuoq
  • 79,187
  • 7
  • 161
  • 281
Destructor
  • 14,123
  • 11
  • 61
  • 126
  • 3
    possible duplicate of [Purpose of static keyword in array parameter of function](http://stackoverflow.com/questions/3430315/purpose-of-static-keyword-in-array-parameter-of-function) – m.s. May 26 '15 at 08:14
  • 1
    Also this [link](http://en.cppreference.com/w/c/language/array) might be helpful. – Maroun May 26 '15 at 08:14

1 Answers1

5

This C99 notation, void foo(double A[static 10]), means that the function can assume that A points to 10 valid arguments (from *A to A[9]). The notation makes programs more informative, helping compilers to both optimize the code generated for the function foo and to check that it is called correctly at each call site.

In the C99 standard, in which the notation was introduced, this is covered by clauses 6.7.5.2 and 6.7.5.3: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”


One common use is f(int p[static 1]), which is more or less equivalent to the notion of reference (as opposed to pointer) in other languages. Clang warns if such a function was declared and is passed a null pointer at the call site (because the notation explicitly means that p will not be NULL). However, the last time I tried, Clang did not warn for f(&a + 1), which is a shame (but a compiler doesn't have to emit all warnings. Emitting some warnings is good already):

#include <stdio.h>

void f(int p[static 1])
{
  printf("%d\n", *p);
}

int main(){
  int a = 0;
  f(&a + 1);
  f(0);
  f(&a);
}

Clang warns for the second call, but unfortunately not for the first one:

$ clang t.c
t.c:11:3: warning: null passed to a callee which requires a non-null argument
      [-Wnonnull]
  f(0);
  ^ ~
t.c:3:12: note: callee declares array parameter as static here
void f(int p[static 1])
           ^~~~~~~~~~~
1 warning generated.

The syntax may seem a little strange, but the C99 standardization committee obviously decided to reuse the pre-existing static keyword in a place that did not cause ambiguity so as to avoid the introduction of a new keyword (that could possibly break existing programs).

Pascal Cuoq
  • 79,187
  • 7
  • 161
  • 281
  • This is not standard. It's instead an Clang extension. And for a reason `void f(int p[static 1])` have the same type as `void f(int p[1])` and `void f(int *p)`!!! GCC for example wouldn't emit such misleading warning. – AnArrayOfFunctions Jun 12 '16 at 14:42
  • @CisNOTthatGOODbutISOisTHATBAD I find it amazing that after I have quoted the clause of the C99 standard that allows this construct, you bother to comment to say that. Also the goal of that construct is exactly to allow Clang's warning to be emitted, so Clang is superior to GCC in this case for emitting it. This is shown in the C99 quote in my answer. – Pascal Cuoq Jun 12 '16 at 14:55
  • @CisNOTthatGOODbutISOisTHATBAD `f` does not look the same as `g` or `h` to me. GCC would be allowed to generate the better code for `f` too (according to the C99 clauses mentioned in my answer), but it is inferior to Clang on this example, as we already said. https://godbolt.org/g/1G54Gc – Pascal Cuoq Jun 12 '16 at 15:11
  • Read my comment [here](http://stackoverflow.com/questions/3430315/what-is-the-purpose-of-static-keyword-in-array-parameter-of-function-like-char/3430353?noredirect=1#comment63065079_3430353). – AnArrayOfFunctions Jun 13 '16 at 21:54
  • @CisNOTthatGOODbutISOisTHATBAD you are saying that compilers are not under obligation to emit warnings. This is true of mostly every warning: only a few “Constraints” sections in the C standard require a diagnostic. That remark does not answer this question, nor does it contradict anything said in this answer. This answer already contains the words “a compiler doesn't have to emit all warnings. Emitting some warnings is good already”. I don't know what you think you are adding to the discussion by claiming `int p[static 1]` is non-standard or with the long two comments you typed elsewhere. – Pascal Cuoq Jun 14 '16 at 08:24
  • Are you certain, that `void f(int p[static 1]){/* ... */} int main(){int a=0; f(&a);}` is not undefined behavior? I've asked the details here: https://stackoverflow.com/questions/62702208/is-it-valid-to-pass-the-address-of-a-non-array-variable-to-a-function-parameter If you are sure, it would be nice, if you could answer that linked question :-) – T S Jul 02 '20 at 18:14
  • @TS Coincidentally I was discussing this with colleagues today in the context of making a static analyzer flag undefined uses of `static` in array argument sizes. I have nothing to add to storyteller's answer: the intent of the C standard is IMO clear and the wording is poor. – Pascal Cuoq Jul 02 '20 at 20:36