标准规定:
5.1.2.2.1程序启动程序启动时调用的函数命名为main。的实现没有为这个函数声明原型。它应该是用返回类型int定义,不带形参Main (void){/*…*/}或带有两个参数(这里称为Argc和argv,尽管可以使用任何名称,因为它们是本地的int main(int argc, char argv[]){/…*/}或同等的;10)或在其他地方实现定义的方式。
如果我这样写:
#include <stdio.h>
struct some_struct
{
int i;
};
float main(struct some_struct s)
{
printf("Why does this main get called?n");
}
实际上,它可以被任何原型调用,正如我看到的,并且没有任何运行时错误。
为什么不禁止?难道没有理由吗?另外,如果签名是错误的,如何调用它?
我用的是gcc (Ubuntu 4.8.2-19ubuntu1) 4.8.2
从标准一致性开始:
1在本国际标准中,"应"被解释为对实施或程序的要求;反之,"不得"则被解释为禁止。
如果"应该"或"不应该"需求出现在约束或运行时约束之外,则行为是未定义的。[…]
看你引用的段落的重点:
[…]。应定义为返回类型int和[…]
在这种情况下,
float main(struct some_struct s){...}
"shall"要求不在约束范围内,因为标准明确规定main
返回类型为int
或者不带参数
int main(void) { /* ... */ }
或带两个参数
int main(int argc, char argv[]) { / ... */ }
这意味着你的程序的行为是未定义的
您在标准中引用的是"一些其他实现定义的方式"。看来gcc在允许什么作为main
的签名方面是相当自由的;它似乎忽略了您传递的参数。如果你用gcc -Wall
编译,你会得到关于main的原型不是它所期望的警告。
clang对main的原型不太宽容。它将接受返回类型float
并给出警告,但会在struct参数上出错。
C仅通过名称查找函数,因此链接器不关心异常的返回类型和参数。
在C语言中,如果一个函数签名没有指定任何实参,这意味着该函数可以带任意数量的形参调用,也可以不带任何形参。
嘿,看看这个链接- https://www.geeksforgeeks.org/difference-int-main-int-mainvoid/