C 单参数Main

C 单参数Main,c,c89,C,C89,我最近遇到一个C程序,其中主函数只接受一个参数。这在C89中合法吗?gcc似乎没有任何问题 我认为签名被忽略,main被称为main(int,char**),但我不确定 在程序中看起来是这样的: main(argc){ ... }是的,它可以工作,但没用 请记住,在C中,任何没有指定类型的变量都默认为int,这意味着函数将扩展为: int main(int argc) { ... } 这在C89中是合法的。但是,大多数情况下,如果您想知道发送到程序的参数数量,您可能需要这些参数的内容,

我最近遇到一个C程序,其中主函数只接受一个参数。这在C89中合法吗?gcc似乎没有任何问题

我认为签名被忽略,main被称为
main(int,char**)
,但我不确定

在程序中看起来是这样的:
main(argc){
...
}

是的,它可以工作,但没用

请记住,在C中,任何没有指定类型的变量都默认为
int
,这意味着函数将扩展为:

int main(int argc) {
    ...
}
这在C89中是合法的。但是,大多数情况下,如果您想知道发送到程序的参数数量,您可能需要这些参数的内容,因此这基本上是无用的

但是,GCC(使用
-Wall
编译时)给了我一个警告:

Only one parameter on 'main' declaration. “main”声明上只有一个参数。 这只是说这段代码非常无用


然而,从技术上讲,@hmjd指出,这是非法的,因为它是未定义的行为。然而,在我遇到的大多数C实现中,当您向函数传递额外的参数时,它们在大多数情况下被忽略。因此,除非您在一个系统上,如果发送给函数的变量数量溢出,那么这很重要,否则您应该不会有问题

根据C89标准,这是不合法的。从第2.1.2.2节托管环境:

程序启动时调用的函数名为“main”。实施 声明此函数没有原型。它可以定义为无参数: int main(void){/*…*/} 或者使用两个参数(此处称为argc和argv,尽管有任何名称) 可以使用,因为它们是声明它们的函数的本地函数): int main(int argc,char*argv[]){/*…*/}
C99标准在第5.1.2.2.1节“程序启动”中也有同样的规定。

我认为这里的措辞很重要,代码可以使用GCC和其他几种编译器编译,但根据C89标准,这是不合法的。这是在一个模糊的C程序中使用的。我知道这是有效的(有点),我更感兴趣的是知道这是否是实际定义的行为(我个人认为在模糊程序中使用非法代码是欺骗);代码是错误的,但编译器没有义务对其做任何特别的处理。它可能会停止转换并发出诊断,也可能会在不进行任何诊断的情况下转换代码,或者在这两者之间进行任何转换。我解释为非法意味着编译器必须发出诊断并停止翻译,这不是这里的情况。标准很好,但我认为真正重要的是它对他目标的编译器有效吗?这里有没有人有一个上面的代码不起作用的编译器?@RichardJ.RossIII,我同意你的看法。然而,OP明确地问这是合法的C89吗?FWIW,微软编译器VC9和VC10编译得很好。不,你是对的,这就是问题所在。我已经知道它是有效的,我只是不知道它是否合法。您省略了该部分的最后一点——“或者以其他实现定义的方式。”一个实现可以自由定义
main
,只要它记录了附加签名,就可以用标准中规定的方式以外的方式定义。话虽如此,我在GCC手册中没有看到任何东西表明这是一个合法的签名,因此行为是未定义的,因此编译器不需要对其发出诊断。此外,我们假设此代码是用于托管实现的;如果它是用于独立实现的,那么所有的赌注都是无效的。@JohnBode,我在C89标准中看不到这一点,但我在C99标准中看到了它,但在这里它是限定的,因此,int可以被定义为int的typedef名称替换,或者argv的类型可以被写为char**argv,依此类推。它没有声明实现可以自由更改签名。 The function called at program startup is named `main`. The implementation declares no prototype for this function. It can be defined with no parameters: int main(void) { /*...*/ } or with two parameters (referred to here as argc and argv , though any names may be used, as they are local to the function in which they are declared): int main(int argc, char *argv[]) { /*...*/ }