Reputation: 21
I have learned from an online class that, both char **argv
and char *argv[ ]
can be used as an argument to main
.
I also understand that they are effectively the same, they both declare argv as a "pointer (*
) to a char pointer (char *
)".
What makes char argv[ ][ ]
invalid as an argument to main
?
edit: Actually, is char *argv[ ]
declaring an array instead of a pointer? So argv only decays to a pointer but is not one itself?
Upvotes: 1
Views: 222
Reputation: 123468
Getting into the weeds a bit:
6.7.6.2 Array declaratorsC 2011 Online Draft
...
1 In addition to optional type qualifiers and the keywordstatic
, the[
and]
may delimit an expression or*
. If they delimit an expression (which specifies the size of an array), the expression shall have an integer type. If the expression is a constant expression, it shall have a value greater than zero. The element type shall not be an incomplete or function type. The optional type qualifiers and the keywordstatic
shall appear only in a declaration of a function parameter with an array type, and then only in the outermost array type derivation.
...
4 If the size is not present, the array type is an incomplete type. If the size is*
instead of being an expression, the array type is a variable length array type of unspecified size, which can only be used in declarations or type names with function prototype scope;143) such arrays are nonetheless complete types. If the size is an integer constant expression and the element type has a known constant size, the array type is not a variable length array type; otherwise, the array type is a variable length array type. (Variable length arrays are a conditional feature that implementations need not support; see 6.10.8.3.)
...
6.7.6.3 Function declarators (including prototypes)
...
4 After adjustment, the parameters in a parameter type list in a function declarator that is part of a definition of that function shall not have incomplete type.
...
7 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 keywordstatic
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.
So, to unpack all of this:
char argv[];
declares argv
as an array of unknown size of char
. This type is incomplete, so we cannot create an array of it with something like
char argv[][N];
and by extension, we can't create an array of unknown size of that element type:
char argv[][];
"But," I hear you say, "a parameter of type char []
is adjusted to type char *
, so why doesn't char [][]
equate to char **
?"
Because that's not how array decay works. Let's start with a generic array declaration
T a[N];
The type of a
is "N-element array of T
", and in most contexts (including as a function parameter), its type is converted ("decays") or "adjusted" to "pointer to T
", which gives us T *a;
.
Now let's replace the type T
with an array type R [M]
. Substituting that in for T
gives us
R a[N][M];
The type of a
is adjusted from "N-array of M-element array of R
" to "pointer to M-element array of R
", which gives us:
R (*a)[M];
not
R **a;
So char argv[][]
will never decay to char **
, it will decay to char (*)[]
(which is an incomplete type and not allowed as a function parameter). But we don't get that far, because char argv[][]
is invalid all on its own.
Upvotes: 1
Reputation: 310990
This declaration of a parameter
char argv[ ][ ]
is invalid because the compiler needs to know the element type of the array that in this case is incomplete type char[]
.
This declaration
char *argv[ ]
declares an incomplete array type with the element type char *
.
If such a declaration is used as a function parameter declaration then it is implicitly adjusted by the compiler to pointer to the element type that is to the declaration
char **argv
Upvotes: 4
Reputation: 43
If you use char argv[ ][ ]
, it is thought every word to have the same amount of letters. Every argv[i], points to another char *
, however, this all new char *
do not need all to be the same size.
Moreover, if you run your code with char argv[ ][ ]
, one error your compilor might show is: "declaration of 'argv' as multidimensional array must have bounds for all dimensions except the first". In fact, the int argc
argument contains the amount of arguments passed, that is how many char * will be allocated. However, there is not any information for the size of the char *
every char * previusly allocated point to.
Upvotes: 0