sna*_*nap 16 c language-design
我正在为我的大学编写一个编译器/语言课程的玩具C编译器.
我试图在C中充实符号解析的语义,并提出了我尝试对常规编译器clang&gcc的测试用例.
void foo() { }
int main() { foo(5); } // foo has extraneous arguments
Run Code Online (Sandbox Code Playgroud)
大多数编译器似乎只是警告无关的论点.
问题:这背后的根本原因是什么?
对于我的符号表生成/解析阶段,我正在考虑一个函数是一个带有返回类型的符号,以及几个参数化的参数(基于语法),每个参数都有一个相应的类型.
谢谢.
pax*_*blo 32
原型中没有列出参数的函数被认为具有不确定的数字,而不是零.
如果你真的想要零参数,它应该是:
void foo (void);
Run Code Online (Sandbox Code Playgroud)
空列表变体是古代C的延续,甚至在ANSI获得它之前,你有这样的东西:
add_one(val)
int val;
{
return val + 1;
}
Run Code Online (Sandbox Code Playgroud)
(int作为声明符外部指定的默认返回类型和参数类型).
如果你正在做一个玩具编译器并且你并不担心每一小块C99的符合性,我只是抛出那个选项并需要某种参数列表.
它会让你的生活变得更加轻松,我怀疑人们是否需要使用这个"功能".
Jer*_*fin 17
它是为了与古老的 C编译器向后兼容.在地球冷却之前,所有C函数声明看起来大致如下:
int foo();
long bar();
Run Code Online (Sandbox Code Playgroud)
等等.这告诉那名被称为函数编译器,但并没有指定有关数量或类型的参数什么.原始(1989)C标准中最大的变化可能是添加了"函数原型",它允许声明参数的数量和类型,因此编译器可以检查调用函数时传递的内容.为了保持现有代码的兼容性,他们决定一个空参数列表将保留其现有含义,如果你想声明一个不带参数的函数,你必须添加void代替参数列表:int f(void);.
请注意,在C++中,情况并非如此 - C++消除了旧样式函数声明,并要求指定所有参数的数量和类型1.如果你声明没有参数的函数,这意味着它不接受任何参数,如果你试图传递任何参数,编译器会抱怨(除非你也重载了函数,所以有另一个具有相同名称的函数可以带参数).
1虽然您仍然可以使用省略号来获取带有变量参数列表的函数 - 但是当/如果这样做,您只能将POD类型作为参数传递.
您尚未提供该foo函数的原型,因此编译器无法强制执行该函数.
如果你写道:
void foo(void) {}
Run Code Online (Sandbox Code Playgroud)
那么你将提供一个不带参数的函数原型.
gcc -Wstrict-prototypes会抓住这个.如有错误,请使用-Werror=strict-prototypes.标准从不指定某些内容应该是警告还是错误.