好的,所以我听到了关于这个主题的不同意见,只是想确保我理解正确.
声明void f();和void f(void);意思完全相同,功能f不带任何参数.同样的定义.
声明void f(void);意味着f不带任何参数.
声明void f();意味着函数f可能有也可能没有参数,如果有,我们不知道它们是什么类型的参数,或者它们有多少参数.请注意,它与省略号不同,我们无法使用va_list.
现在这里的事情变得有趣了.
宣言:
void f();
定义:
void f(int a, int b, float c)
{
   //...
}
宣言:
void f();
定义:
void f()
{
   //...
}
当我们f使用正确的参数,错误的参数和根本没有参数调用时,在情况1和2的编译时会发生什么?运行时会发生什么?
如果我f用参数声明,但没有它们来定义它,它会有所作为吗?我应该能够解决函数体中的参数吗?
Die*_*Epp 53
更多术语(C,而不是C++):函数的原型声明其参数的类型.否则该函数没有原型.
void f();                      // Declaration, but not a prototype
void f(void);                  // Declaration and prototype
void f(int a, int b, float c); // Declaration and prototype
从K&R C时代开始,非原型的声明就是来自ANSI C之前的保留.使用旧式声明的唯一原因是保持与旧代码的二进制兼容性.例如,在Gtk 2中有一个没有原型的函数声明 - 它是偶然的,但是如果不破坏二进制文件就不能删除它.C99标准评论:
6.11.6函数声明符
使用带有空括号的函数声明符(不是prototype-format参数类型声明符)是一个过时的功能.
建议:我建议编译所有的C代码在GCC /铛与-Wstrict-prototypes和-Wmissing-prototypes,除了通常的-Wall -Wextra.
void f(); // declaration
void f(int a, int b, float c) { } // ERROR
声明不同意功能机构!这实际上是一个编译时错误,这是因为你float没有原型的函数中没有参数.你不能float在非原型函数中使用a的原因是因为当你调用这样一个函数时,所有参数都会使用某些默认促销来提升.这是一个固定的例子:
void f();
void g()
{
    char a;
    int b;
    float c;
    f(a, b, c);
}
在这个程序中,a被提升为int1并c被提升为double.所以定义f()必须是:
void f(int a, int b, double c)
{
    ...
}
见C99 6.7.6第15段,
如果一个类型具有参数类型列表而另一个类型由函数声明符指定,该函数声明符不是函数定义的一部分并且包含空标识符列表,则参数列表不应具有省略号终止符,并且每个参数的类型应为与应用默认参数促销产生的类型兼容.
当我们
f使用正确的参数,错误的参数和根本没有参数调用时,在情况1和2的编译时会发生什么?运行时会发生什么?
当您致电时f(),参数将使用默认促销进行宣传.如果提升的类型与实际参数类型匹配f(),那么一切都很好.如果它们不匹配,它可能会编译,但你肯定会得到未定义的行为.
"未定义的行为"是指"我们不保证会发生什么".也许你的程序会崩溃,也许它会正常工作,也许会邀请你的公婆吃饭.
有两种方法可以在编译时获得诊断.如果您有一个具有跨模块静态分析功能的复杂编译器,那么您可能会收到一条错误消息.您还可以使用GCC获取非原型函数声明的消息-Wstrict-prototypes- 我建议您在所有项目中打开(使用Gtk 2的文件除外).
如果我
f用参数声明,但没有它们来定义它,它会有所作为吗?我应该能够解决函数体中的参数吗?
它不应该编译.
实际上有两种情况允许函数参数不同意函数定义.
可以传递char *给期望的函数,void *反之亦然.
可以将有符号整数类型传递给期望该类型的无符号版本的函数,反之亦然,只要该值在两种类型中都是可表示的(即,它不是负数,并且不在范围之外)签名类型).
1:这是有可能的是char提升到unsigned int,但是这是非常罕见的.
如果您使用的是C99或更高版本(并且除非您坚持使用旧的嵌入式系统或类似的东西,您可能应该使用更现代的东西),整个事情真的是一个没有实际意义的事情.
C99/C11部分6.11.6 Future language directions, Function declarators规定:
使用带有空括号的函数声明符(不是prototype-format参数类型声明符)是一个过时的功能.
因此,你应该避免使用像这样的东西void f();.
如果它需要参数,列出它们,形成一个合适的原型.如果没有,我们void明确表示它不采取任何参数.
| 归档时间: | 
 | 
| 查看次数: | 20409 次 | 
| 最近记录: |