C 调用了签名错误的main()函数

C 调用了签名错误的main()函数,c,main,C,Main,标准上说: 5.1.2.2.1程序启动 程序启动时调用的函数名为main。这个 实现没有声明此函数的原型。应该是 使用返回类型int定义,但不带参数:int main(void){/*…*/}或具有两个参数(此处称为 argc和argv,但可以使用任何名称,因为它们是 声明它们的函数):int main(int argc,char argv[] {/..*/}或同等产品;10) 或者在其他方面 实现定义方式 如果我这样写: #include <stdio.h> struct som

标准上说:

5.1.2.2.1程序启动

程序启动时调用的函数名为main。这个 实现没有声明此函数的原型。应该是 使用返回类型int定义,但不带参数: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");
}
#包括
构造某个结构
{
int i;
};
浮动干管(某些结构)
{
printf(“为什么调用此主节点?\n”);
}
实际上,正如我所看到的,任何原型都会调用它,并且没有任何运行时错误

为什么不禁止呢?没有理由吗?另外,如果签名错误,如何调用它


我使用了
gcc(Ubuntu 4.8.2-19ubuntu1)4.8.2

您在标准中的引用声明“其他一些实现定义方式”。似乎gcc在允许作为
main
的签名方面相当自由;它似乎忽略了您正在传递的参数。如果您使用
gcc-Wall
进行编译,您会收到关于main的原型与预期不符的警告

clang对main的原型不太宽容。它将接受带有警告的返回类型
float
,但将在struct参数上出错


C只按名称查找函数,因此链接器不关心异常的返回类型和参数

从标准一致性开始:

1在本国际标准中,“应”应解释为对实施或程序的要求;相反,“不得”应解释为禁止

2如果违反了约束或运行时约束之外出现的“应”或“不应”要求,则行为未定义。[……]

看看你引用的段落的重点:

[……]。应使用返回类型int和[…]对其进行定义

在这种情况下,

float main(struct some_struct s){...}  
“应”要求不受约束,因为标准明确规定
main
返回类型应为
int
,且不带任何参数

int main(void) { /* ... */ }  
 int main(int argc, char argv[]) { / ... */ }    
或具有两个参数

int main(void) { /* ... */ }  
 int main(int argc, char argv[]) { / ... */ }    

这意味着程序的行为是未定义的。

在C中,如果函数签名没有指定任何参数,则意味着可以使用任意数量的参数或不使用任何参数来调用函数


嘿,签出这个链接-

-Wall-Werror
-pedantic errors
编译,你会看到它是不允许的。基本上,如果main()没有类型化,它默认为int,如果它是类型化的,而不是int——这是一个错误。了解编译标志,但是如何调用它呢?它只查找名为“main”的函数并忽略任何参数?C中的链接器只查看函数名。包括链接中的参数是C++特性,支持函数重载所需。被称为“名字弄乱”,我知道了。谢谢我可能会写一个答案,这样我就可以接受了,这真是奇怪的叮当声。感觉不对。没有返回类型
int
(因为不可能有格式良好的程序也有
float main(…)
,因为
main
不能重载),这应该是一个适当的错误。但是,实现可以自由支持
main
的任何类型的参数,因此可以说“您的签名已被忽略”或“您的签名已被忽略”,并且仍然符合要求。“实现定义”是指实现定义了它,也就是说,它在文档中声明了它。当使用GCC编译并执行程序时,程序似乎“工作”,这一事实并不意味着行为是由实现定义的。@KerrekSB:C标准允许实现支持除
int
for
main
以外的返回类型;C 2018 5.1.2.2.1规定应定义
main
“……或以其他实现定义的方式。”然而,我不认为这是Clang在这里所做的。相反,声明
main
的要求不是约束,C标准也不要求编译器因为它们而拒绝翻译程序。正如C 2018注释9所说,“…[一个实现]还可以成功地翻译一个无效的程序…”@KerrekSB:注释5.1.2.2.3 1:“如果
main
函数的返回类型与
int
兼容,…”,因此标准明确规定了
main
的其他返回类型{…}是未定义的行为吗?我在C89.C99中看到过它,后者反对使用此签名。我们还可以看到main带有第三个参数:环境变量。cf。此答案省略了它引用的段落的部分文本。根据C 2018 5.1.2.2.1,可以定义
main
“…或以某种其他实现定义的方式。”5.1.2.2.1 1中可能存在一些问题,即句子结构是否使“或”仅适用于参数或返回类型。然而,5.1.2.2.3 1明确了标准对其他返回类型的规定:“如果
main
函数的返回类型与
int
兼容,…如果返回类型与
int
不兼容,…”