char argv [] []作为主要函数参数,为什么不呢?

问题描述

我从在线课程中学到,char **argvchar *argv[ ]都可以用作main的参数。

我也了解它们实际上是相同的,它们都将argv声明为“指向char指针(*)的指针(char *)”。

是什么使char argv[ ][ ]作为main的参数无效?

edit:实际上,char *argv[ ]是在声明数组而不是指针吗?那么argv只衰减到一个指针,而不是自身吗?

解决方法

此参数声明

char argv[ ][ ]

无效,因为编译器需要知道在这种情况下为不完整类型char[]的数组的元素类型。

此声明

char *argv[ ] 

声明元素类型为char *的不完整数组类型。

如果将此类声明用作函数参数声明,则编译器会隐式地将其调整为指向该声明所指向的元素类型的指针

char **argv
,

有点杂草:

6.7.6.2数组声明符
...
1除了可选的类型限定符和关键字static之外,[]还可定界 表达式或*。如果它们定界表达式(指定数组的大小),则 表达式应具有整数类型。如果表达式是一个常量表达式,则应为 值大于零。 元素类型不得为不完整或功能 输入 。可选的类型限定符和关键字static仅出现在 具有数组类型的函数参数的声明,然后仅在最外面 数组类型派生。
...
4 如果不存在大小,则数组类型为不完整的类型 。如果大小是*而不是 作为表达式,数组类型是未指定大小的可变长度数组类型, 只能在声明或具有函数原型范围的类型名称中使用; 143) 这样的数组仍然是完整的类型。如果大小是整数常量表达式 并且元素类型具有已知的恒定大小,数组类型不是可变长度 数组类型;否则,数组类型为可变长度数组类型。 (可变长度 数组是实现不需要支持的条件功能;参见6.10.8.3。)
...
6.7.6.3函数声明符(包括原型)
...
4 调整后,函数声明器中的参数类型列表中的参数即为 该函数的定义的一部分不能具有不完整的类型。
...
7 将参数声明为“ 类型的数组”声明应调整为“ type ’”,其中类型限定符(如果有)是在“ {em}”的[和{{1} 。如果关键字]也出现在列表的static[中 数组类型推导,则对于每次调用该函数,对应的值 实参应提供对数组第一个元素的访问,至少要有尽可能多的元素 由size表达式指定的元素。
C 2011 Online Draft

因此,要打开所有这些包装:

]

char argv[]; 声明为argv大小未知的数组。此类型为不完整,因此我们无法使用类似

的内容来创建该数组
char

并且通过扩展,我们不能创建该元素类型的未知大小的数组:

char argv[][N];

“但是,”我听到您说,“类型char argv[][]; 的参数已调整为类型char [],那么char *为什么不等于char [][]? “

因为这不是数组衰减的工作方式。让我们从通用数组声明开始

char **

T a[N]; 的类型是“ a的N元素数组”,并且在大多数情况下(包括作为函数参数),其类型将被转换(“衰减”)或“调整”指向“ T的指针”,这给了我们T

现在让我们用数组类型T *a;替换类型T。用in代替R [M]给我们

T

R a[N][M]; 的类型从“ a的M元素数组的N数组”调整为“指向R的M元素数组的指针”,这使我们:

R

不是

R (*a)[M];

因此R **a; 永远不会衰减到char argv[][],它将衰减到char **(这是不完整的类型,不允许作为函数参数)。但是我们并没有走太远,因为char (*)[]本身就无效。

,

如果使用char argv[ ][ ],则认为每个单词都具有相同数量的字母。每个argv [i]都指向另一个char *,但是,所有这些新的char *都不需要大小都相同。

此外,如果您使用char argv[ ][ ]运行代码,则编译器可能会显示一个错误:“将'argv'声明为多维数组必须对除第一个维度之外的所有维度都具有边界”。实际上,int argc参数包含传递的参数数量,即将分配多少char *。但是,没有任何关于每个字符*先前分配的点char *的大小的信息。