在C中,我应该定义(不声明/原型)一个不带void参数或空列表的函数吗?

Ras*_*edi 1 c

这个问题可能有也可能没有,虽然我试图找到一个,但每个人的答案似乎只是指的是声明/原型.它们指定定义void foo() { }是相同的void foo(void) { },但我应该以哪种方式实际使用?在C89?在C99?我相信我应该开始使用void foo(void);我的原型声明,但如果我使用void或不使用定义,是否有任何区别?

flu*_*ter 9

它们是不同的,void foo(void)声明foo为一个带有NO参数的函数,并且不返回任何内容.

而对于void foo(),该函数foo接受了大量的参数,并返回void.

你应该总是使用第一个标准符合C.


Mat*_*ira 5

它们在语义上是不同的

鉴于以下功能:

void f(void);
void g();
Run Code Online (Sandbox Code Playgroud)

f使用参数调用是编译时错误:

error: too many arguments to function "f"
Run Code Online (Sandbox Code Playgroud)

但是,这种声明g意味着它需要一些未指定数量的参数.对于编译器,这意味着它可以采用任意数量的参数,从零到某个实现定义的上限.编译器将接受:

g();
g(argument);
g(argument1, argument2, ... , argumentN);
Run Code Online (Sandbox Code Playgroud)

本质上,因为g没有指定它的参数,编译器并不真正知道有多少参数g接受.因此编译器将接受任何内容并根据实际使用情况发出代码g.如果传递一个参数,它将发出代码以推送一个参数,调用g然后将其从堆栈中弹出.

这是明确说"不,我不接受任何争论"而不是在被质疑时说什么之间的区别.剩余的静默使问题g变得模糊,以至于调用语句是编译器关于函数接受哪些参数的唯一具体信息.因此,它将根据规范发出机器代码.

建议

我应该以哪种方式使用?

根据SEI CERT C编码标准,建议明确指定void函数何时不接受任何参数.

该文引用了C11标准,第6.11.6节作为其建议的基础:

使用带有空括号的函数声明符(不是prototype-format参数类型声明符)是一个过时的功能.

声明具有未指定参数列表的函数被归类为中等严重性.提出了可能出现的问题的具体例子.即:

  1. 模糊界面
    • 编译器不会执行检查
    • 可能会隐藏错误
  2. 信息流出
    • 潜在的安全漏洞

信息安全不仅探索安全性,还探索两种风格的编程和软件开发含义.

问题更多的是质量保证. 旧式声明是危险的,不是因为邪恶的程序员,而是因为人类程序员,他们无法想到一切,必须得到编译器警告的帮助.这就是ANSI C中引入的函数原型的所有要点,其中包括函数参数的类型信息.