Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the point of specifying the size of an array in a parameter declaration?

Tags:

arrays

c

pointers

#include <stdio.h>

int a[] = {1,2};

void test(int in[3]){
  //
}
 
int main() {
 test(a); 
 return 0;
}

In the above code int in[3] is the same as int *in. The number 3 doesn't really do anything and it's not even the correct size, but even so the compiler doesn't complain. So is there a reason this syntax is accepted in C or I'm missing a functionality?

like image 483
Dan Avatar asked Nov 19 '20 04:11

Dan


1 Answers

When an array parameter declaration contains a constant size, the only purpose it can serve is as documentation for readers, by indicating to them what size array the function expects. For a constant expression n, the compiler converts an array declaration such as int in[n] to int *in, after which there is no difference to the compiler and so nothing is affected by the value of n.

Originally in C, function parameters were specified by a list of declarations after the initial function declaration, such as:

int f(a, b, c)
int a;
float b;
int c[3];
{
    … function body
}

I conjecture that array sizes were permitted in these declarations simply because they used the same grammar as other declarations. It would have been harder to write compiler code and documentation that excluded the sizes than to simply allow them to occur but to ignore them. When declaring paramter types inside function prototypes (int f(int a, float b, int c[3])) was introduced, I conjecture the same reasoning applied.

However:

  • If the declaration contains static, as in int in[static n], then, when the function is called, the corresponding argument must point to at least n elements, per C 2018 6.7.6.3 7. Compilers may use this for optimization.
  • If the array size is not a constant, it may be evaluated by the compiler when the function is called. For example, if the function declaration is void test(int in[printf("Hi")]), then both GCC 10.2 and Apple Clang 11.0 print “Hi” when the function is called. (However, it is not clear to me the C standard requires this evaluation.)
  • This adjustment occurs only for the actual array parameter, not arrays within it. For example, in the parameter declaration int x[3][4], the type of x is adjusted to be int (*)[4]. The 4 remains a part of the size and has effects on pointer arithmetic with x.
  • When a parameter is declared as an array, the element type must be complete. In contrast, a parameter declared as a pointer need not point to a complete type. For example, struct foo x[3] yields a diagnostic message if struct foo has not been fully defined, but struct foo *x does not.
like image 79
Eric Postpischil Avatar answered Sep 27 '22 20:09

Eric Postpischil