为什么未定义大小的数组只允许在 main() 中使用?

Why are arrays of undefined size only allowed in main()?

main 方法参数使用了未定义的数组 argv[]

int main(int argc, char *argv[])
{
 .... Do stuff....
}

为什么只允许在 main() 方法中使用未定义的数组?

我对这个问题有点困惑。 argc 是传递给可执行文件的命令行参数的数量。 argv 是这些参数的数组。两者都不是未定义的。

argcargv都是简单的参数名,你可以随意更改。按照惯例,它们简称为 argcargv

其实这个声明

int main(int argc, char *argv[])

相当于

int main(int argc, char **argv)

主机环境提供了一个字符串数组,并将指向数组中第一个字符串的指针作为参数 argv.

的参数传递

来自C标准(5.1.2.2.1程序启动)

— If the value of argc is greater than zero, the array members argv[0] through argv[argc-1] inclusive shall contain pointers to strings, which are given implementation-defined values by the host environment prior to program startup. The intent is to supply to the program information determined prior to program startup from elsewhere in the hosted environment. If the host environment is not capable of supplying strings with letters in both uppercase and lowercase, the implementation shall ensure that the strings are received in lowercase

至于评论

The argv array has no size, how is this possible?

然后声明为T类型数组的函数参数被调整为指向T的指针。

例如这些函数声明

void f( int a[100] );
void f( int a[10] );
void f( int a[] );

声明同一个函数,所有声明调整为声明

void f( int *a );

将数组类型的参数传递给函数时的方式相同,然后数组将隐式转换为指向其第一个元素的指针。

所以例如上面的函数可以这样调用

int a[100];
f( a );

int a[10];
f( a );

int *a;
f( a );

这里main没什么特别的。 char *argv[]int example[] 等数组声明具有 不完整类型 ,这在某些上下文中有效,但在其他上下文中无效。但是,在函数的参数声明中,最终类型不能是数组类型;数组符号充当指向该类型数组第一个成员的指针的替代。 mainargv的实际类型是char **.

Why is it undefined arrays are only allowed in the main() method?

"undefined arrays" 你似乎是指未指定大小的数组。有几种不同的情况需要考虑。

  1. 用数组语法声明的函数参数不管是否指定了bound,实际上毕竟没有数组类型。相反,这样的参数具有 pointer 类型。没有必要指定边界(对于第一个维度),如果指定了边界则它是微不足道的。这与从数组到指针的自动转换 ("decay") 相匹配,如果相应的参数是一个数组,调用者会发生这种情况,但在被调用的函数中,参数是一个指针,一个完整的指针,仅此而已一个指针。

    这适用于任何函数,而不仅仅是main()

  2. 任何变量 都可以在文件或块范围内声明为数组,没有显式绑定但带有初始化程序;在这种情况下,数组边界被隐式建立为容纳由初始化程序初始化的所有元素所需的最小值。

    示例:

    int some_primes[] = { 2, 3, 5, 7, 11 };  // dimension 5
    
  3. 一个文件作用域(在任何函数之外)变量或一个有链接的变量可以被声明为一个没有显式边界的数组并且没有初始化器 来隐式建立绑定。这种变量的类型是 "incomplete" 直到并且除非同一变量的另一个兼容声明通过提供边界来完成它,但是可以在源代码中它保持不完整的点上对其执行许多数组操作。

  4. 只有 数组类型且没有初始值设定项的局部变量 必须使用显式绑定声明。 ("Local variables" 是在块范围内声明的,没有链接。)不过,这是一个相当常见的情况,所以我想需要为它们声明一个大小是这个问题的部分灵感。