char argv[ ][ ] 作为主要函数参数,为什么不呢?
char argv[ ][ ] as main function argument, why not?
我从网上了解到 class,char **argv
和 char *argv[ ]
都可以用作 main
的参数。
我也明白它们实际上是一样的,它们都将 argv 声明为“指向 char 指针 (char *
) 的指针 (*
)”。
是什么让 char argv[ ][ ]
作为 main
的参数无效?
编辑:实际上,char *argv[ ]
声明的是数组而不是指针吗?所以 argv 只会衰减为一个指针,而不是指针本身?
如果使用char argv[ ][ ]
,则认为每个单词都有相同数量的字母。每个 argv[i] 都指向另一个 char *
,但是,这个全新的 char *
不需要全部相同。
此外,如果您 运行 您的代码带有 char argv[ ][ ]
,您的编译器可能会显示一个错误:“声明 'argv' 作为多维数组必须对所有维度都有边界,除了第一的”。事实上,int argc
参数包含传递的参数数量,即分配多少 char *。但是,没有任何关于 char *
every char * previusly allocated point to.
大小的信息。
这个参数声明
char argv[ ][ ]
无效,因为编译器需要知道数组的元素类型,在这种情况下是不完整类型 char[]
。
这个声明
char *argv[ ]
声明了一个元素类型为 char *
的不完整数组类型。
如果这样的声明用作函数参数声明,则编译器会将其隐式调整为指向声明的元素类型的指针
char **argv
深入了解一下:
6.7.6.2 Array declarators
...
1 In addition to optional type qualifiers and the keyword static
, 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 keyword static
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 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.
C 2011 Online Draft
所以,解压所有这些:
char argv[];
将 argv
声明为大小为 char
的未知数组。这种类型 不完整 ,所以我们不能用类似
的东西创建它的数组
char argv[][N];
并且推而广之,我们无法创建该元素类型的未知大小的数组:
char argv[][];
“但是,”我听到你说,“char []
类型的参数被调整为 char *
类型,那么为什么 char [][]
不等于 char **
?"
因为这不是数组衰减的工作原理。让我们从通用数组声明开始
T a[N];
a
的类型是“N-element T
的数组”,并且在大多数情况下(包括作为函数参数),它的类型被转换(“decays”)或“调整”为“指向 T
的指针”,这给了我们 T *a;
.
现在让我们用数组类型 R [M]
替换类型 T
。将其替换为 T
得到
R a[N][M];
a
的类型从“N-array of M-element array of R
”调整为“pointer to M-element array of [=42]” =]”,这给了我们:
R (*a)[M];
不是
R **a;
所以char argv[][]
永远不会衰减到char **
,它会衰减到char (*)[]
(这是一个不完整的类型,不允许作为函数参数)。但我们还没有走到那一步,因为 char argv[][]
本身是无效的。
我从网上了解到 class,char **argv
和 char *argv[ ]
都可以用作 main
的参数。
我也明白它们实际上是一样的,它们都将 argv 声明为“指向 char 指针 (char *
) 的指针 (*
)”。
是什么让 char argv[ ][ ]
作为 main
的参数无效?
编辑:实际上,char *argv[ ]
声明的是数组而不是指针吗?所以 argv 只会衰减为一个指针,而不是指针本身?
如果使用char argv[ ][ ]
,则认为每个单词都有相同数量的字母。每个 argv[i] 都指向另一个 char *
,但是,这个全新的 char *
不需要全部相同。
此外,如果您 运行 您的代码带有 char argv[ ][ ]
,您的编译器可能会显示一个错误:“声明 'argv' 作为多维数组必须对所有维度都有边界,除了第一的”。事实上,int argc
参数包含传递的参数数量,即分配多少 char *。但是,没有任何关于 char *
every char * previusly allocated point to.
这个参数声明
char argv[ ][ ]
无效,因为编译器需要知道数组的元素类型,在这种情况下是不完整类型 char[]
。
这个声明
char *argv[ ]
声明了一个元素类型为 char *
的不完整数组类型。
如果这样的声明用作函数参数声明,则编译器会将其隐式调整为指向声明的元素类型的指针
char **argv
深入了解一下:
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.
所以,解压所有这些:
char argv[];
将 argv
声明为大小为 char
的未知数组。这种类型 不完整 ,所以我们不能用类似
char argv[][N];
并且推而广之,我们无法创建该元素类型的未知大小的数组:
char argv[][];
“但是,”我听到你说,“char []
类型的参数被调整为 char *
类型,那么为什么 char [][]
不等于 char **
?"
因为这不是数组衰减的工作原理。让我们从通用数组声明开始
T a[N];
a
的类型是“N-element T
的数组”,并且在大多数情况下(包括作为函数参数),它的类型被转换(“decays”)或“调整”为“指向 T
的指针”,这给了我们 T *a;
.
现在让我们用数组类型 R [M]
替换类型 T
。将其替换为 T
得到
R a[N][M];
a
的类型从“N-array of M-element array of R
”调整为“pointer to M-element array of [=42]” =]”,这给了我们:
R (*a)[M];
不是
R **a;
所以char argv[][]
永远不会衰减到char **
,它会衰减到char (*)[]
(这是一个不完整的类型,不允许作为函数参数)。但我们还没有走到那一步,因为 char argv[][]
本身是无效的。