Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is the syntax "int (*)[*]" necessary in C?

Tags:

Just was looking something up in the ISO/IEC9899 When I stumbled on this:

6.7.6 Type names

[...]

Semantics

2 In several contexts, it is necessary to specify a type. This is accomplished using a type name, which is syntactically a declaration for a function or an object of that type that omits the identifier.128) 3 EXAMPLE The constructions

(a) int (b) int * (c) int *[3] (d) int (*)[3] (e) int (*)[*] (f) int *() (g) int (*)(void) (h) int (*const [])(unsigned int, ...) 

name respectively the types (a) int, (b) pointer to int, (c) array of three pointers to int, (d) pointer to an array of three ints, (e) pointer to a variable length array of an unspecified number of ints, (f) function with no parameter specification returning a pointer to int, (g) pointer to function with no parameters returning an int, and (h) array of an unspecified number of constant pointers to functions, each with one parameter that has type unsigned int and an unspecified number of other parameters, returning an int.

What most confused me was:

(e) pointer to a variable length array of an unspecified number of ints

The others I can understand more or less. But what is the use of a pointer to a VLA of unspecified number of 'ints'?

And is there even a need for compiler's to support the syntax of

int foo[*]; 

?

EDIT for clarification

This Question primaly aims on "Is it even neccessary to support this for a compiler?". Whilest this post ANSI-C grammar - array declarations like [*] et alii clearly improved my knowledge. There is still no answer for: Why does the compiler need to know if the parameter of the prototype just is a address containing unknown size. as with simply doing int foo[] or it will be unspecified size?

So is this realy neccessary to be supported? And if not so, why the standard even is implementing this semantic?

like image 954
dhein Avatar asked Dec 17 '14 15:12

dhein


People also ask

What is the use of int * in C?

int: As the name suggests, an int variable is used to store an integer. float: It is used to store decimal numbers (numbers with floating point value) with single precision. double: It is used to store decimal numbers (numbers with floating point value) with double precision.

Why do we use * in C?

Answer: * Operator is used as pointer to a variable. Example: * a where * is pointer to the variable a. & operator is used to get the address of the variable.

Why do we use * Before variable in C?

While * means the address of a variable in C programming language, what does ** mean then? Actually, & means the address of a variable. * means the value at an address, which also known as dereferencing. In that sense, ** just is dereferencing twice.

What is the significance of & and * operators?

&,* Operator: Pointer operator & returns the address of a variable. For example &a; will give the actual address of the variable. Pointer operator * is a pointer to a variable.


1 Answers

Why does the compiler need to know if the parameter of the prototype just is a address containing unknown size. as with simply doing int foo[] or it will be unspecified size?

The compiler doesn't need to "know" anything, it's a tool.

The difference between int (*)[*] and int[] is about the same as between int (*)[5] and int[]. If you agree that the latter pair is not interchangeable, then the former isn't either.

In pre-C99, the way to specify an array of unknown number of T elements is T[]. This is an incomplete type, which means you cannot have an array of T[]. There is no T[][]. Inside a function declarator, T[] means the same as T*. OTOH T[*] is a variable-length array, which is different from an array of unknown number of elements. You can have an array of variable-size arrays, i.e. there is T[*][*]. The syntax you are asking about is necessary to support this variable-size-array type. Luckily you are not asking why we need different types, because the answer would be really long-winded, but here's my stab at it.

The purpose of types is two-fold. First, types are needed for object code generation (things like a++ typically generate different object code, depending on the type of a). Second, types are needed for type-checking (things like a++ may be allowed or not depending on the type of a).

The [*] types are only allowed in function declarators that are not parts of function definitions. So code generation and is not relevant here. This leaves us with type checking. Indeed,

int foo(int, int (*)[*]); int bar(int, int (*)[5]);  int main () {     int a;     int aa[5];     int aaa[5][5];      foo(1, &a);    // incorrect, `&a` is `int*`, `int*` and `int (*)[*]` are different     bar(1, &a);    // incorrect, `&a` is `int*`, `int*` and `int (*)[5]` are different     foo(5, aa);    // incorrect, `aa` is `int*` (!), `int*` and `int (*)[*]` are different     bar(5, aa);    // incorrect, `aa` is `int*` (!), `int*` and `int (*)[5]` are different     foo(5, &aa);   // correct     bar(5, &aa);   // correct     foo(5, aaa);   // correct     bar(5, aaa);   // correct } 

If we are agree on which calls to bar are correct and which are not, we must agree also on calls to foo.

The only remaining question is, why int foo(int m, int (*)[m]); is not enough for this purpose? It probably is, but the C language does not force the programmer to name formal parameters in function declarators where parameter names are not needed. [*] allows this small freedom in case of VLAs.

like image 186
n. 1.8e9-where's-my-share m. Avatar answered Oct 08 '22 13:10

n. 1.8e9-where's-my-share m.