By the way, one thing that came up for me last week was that we probably ought to mention conformant array parameters. For example,
int f(size_t n, int a[n])
is a handy way to document the size of an array parameter.
Standard Examples
Section 6.7.6.3 of C11 has several examples of conformant array parameters. Example 4 illustrates a variably modified parameter:
void addscalar(int n, int m, double a[n][n*m+300], double x); int main() { double b[4][308]; addscalar(4, 2, b, 2.17); return 0; } void addscalar(int n, int m, double a[n][n*m+300], double x) { for (int i = 0; i < n; i++) for (int j = 0, k = n*m+300; j < k; j++) // a is a pointer to a VLA with n*m+300 elements a[i][j] += x; }
Example 5 illustrates a set of compatible function prototype declarators
double maximum(int n, int m, double a[n][m]); double maximum(int n, int m, double a[*][*]); double maximum(int n, int m, double a[ ][*]); double maximum(int n, int m, double a[ ][m]);
These prototype declarators are also compatible:
void f(double (* restrict) a)[5]); void f(double a[restrict][5]); void f(double a[restrict 3][5]); void f(double a[restrict static 3][5]);
C11 concludes with the following note regarding example 5:
Note that the last declaration also specifies that the argument corresponding to a in any call to f must be a
non-null pointer to the first of at least three arrays of 5 doubles, which the others do not.
Noncompliant Code Example
void my_memset(char* p, size_t n, char v) { memset( p, v, n); }
Noncompliant Code Example
This doesn't compile because n
is used before being declared.
void my_memset(char p[n], size_t n, char v) { memset( p, v, n); }
Compliant Solution
void my_memset(size_t n, char p[n], char v) { memset( p, v, n); }
Bibliography
C99, section 6.7.6.3 (see example 4)