理解在C和C ++ F()和f(空隙)之间​​的差值一劳永逸 [英] Understanding the difference between f() and f(void) in C and C++ once and for all

查看:140
本文介绍了理解在C和C ++ F()和f(空隙)之间​​的差值一劳永逸的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


  

可能重复:结果
  是现代pcated F(无效)德$ P $ C和C ++


好了,我听说过关于这个问题的不同意见,只是想确认我理解正确了。

对于C ++

声明无效F(); 无效F(无效); 的意思是precisely同样的事情,函数˚F不带任何参数。同上,用于定义。

对于C

宣言无效F(无效); 表示˚F不带任何参数。

宣言无效F(); 表示函数˚F可能会或可能不会有参数,如果它不我们不知道这些是什么样的参数,或者有多少是其中。请注意,这是不一样的省略号,我们不能使用的va_list

现在这里是事情变得有趣。

案例1

声明:

 无效F();

定义:

 无效F(int类型的,INT B,浮动三)
{
   // ...
}

案例2

声明:

 无效F();

定义:

 无效F()
{
   // ...
}

问:

在案件1在编译的时候会发生什么和2当我们调用˚F使用正确的参数,错误的参数和没有参数呢?在运行时会发生什么?

其他问题:

如果我宣布˚F带参数,而是将其定义没有他们,这会有所作为?我应该能够从函数体解决争论?


解决方案

更​​多的术语(C,而不是C ++):一个原型的函数声明的类型它的参数。否则,该函数没有原型。

 无效F(); //宣言,但不是一个原型
无效F(无效); //宣言和原型
无效F(int类型的,INT B,浮点C); //宣言和原型

声明是不原型是从pre-ANSI C遗留下来的,从K&放天; R C.使用旧式声明的唯一原因是为了保持与旧code二进制兼容性。例如,在GTK 2有无原型函数声明 - 它是有由意外,但它可以不破坏二进制除去。 C99标准的意见:


  

6.11.6函数声明


  
  

使用的函数声明与空括号(没有原型的格式参数
  类型的声明)是一个过时的功能。


建议:我建议在编译GCC / Clang的所有C code。与 -Wstrict的原型 -Wmissing的原型,除了通常的 -Wall -Wextra

会发生什么

 无效F(); // 宣言
无效F(int类型的,INT B,浮法三){} //错误

该声明不同意函数体!这实际上是一个的编译时间的错误,这是因为你不能有一个浮动参数的函数没有原型。究其原因,你不能在unprototyped功能使用浮动是因为当你调用这样的功能,所有的参数都使用某些默认促销活动得到提升。这里有一个固定的例子:

 无效F();无效克()
{
    所以char a;
    INT B:
    浮℃;
    F(A,B,C);
}

在这个程序中, A 提升为 INT 1 C 提升为双击。因此,对于 F()的定义必须是:

 无效F(int类型的,INT B,双c)
{
    ...
}

请参阅C99 6.7.6第15段,


  

如果一种类型的具有一个参数类型列表,并通过一个指定的其它类型的
  函数声明这不是一个函数定义的一部分,包含一个空
  标识符列表,参数列表中不应有一个省略号终结,每个类型
  参数应与从的结果的应用的类型兼容
  默认参数提升。


答1


  

在案件1在编译的时候会发生什么和2当我们调用˚F使用正确的参数,错误的参数和没有参数呢?在运行时会发生什么?


当你调用 F(),参数获取使用默认促销推广。如果提拔类型匹配的实际参数类型 F(),那么一切都很好。如果它们不匹配,它会的可能的编译,但你一定会得到未定义的行为。

未定义行为是规范-代言我们不作任何关于会发生什么保证。也许你的程序将会崩溃,也许它会正常工作,也许它会邀请你的公婆家吃饭。

有两种方法可以在编译时诊断。如果你有一个复杂的编译器,跨模块的静态分析功能,那么你可能会得到一个错误信息。您还可以得到非原型函数声明的消息与海湾合作委员会,使用 -Wstrict的原型 - 我建议所有的项目开启(除了文件,这些文件使用GTK 2)。

答2


  

如果我宣布˚F带参数,而是将其定义没有他们,这会有所作为?我应该能够从函数体解决争论?


它不应该编译。

例外

实际上有两种情况,即,函数参数允许与函数定义不同意。


  1. 这是好到的char * 传递给需要无效* ,反之亦然功能


  2. 这是好到有符号整数类型传递给需要这种类型的,反之亦然的无符号版本的函数,只要值重新在这两种类型的presentable(也就是说,它是不是消极的,而不是出了符号类型的范围内)。


脚注

1 :是的可能的是字符提升到 unsigned int类型,但是这是非常罕见的。

Possible Duplicate:
is f(void) deprecated in modern C and C++

Ok, so I have heard different opinions on this subject and just want to make sure I understand it correctly.

For C++

Declarations void f(); and void f(void); mean precisely the same thing, the function f does not take any parameters. Ditto for definitions.

For C

Declaration void f(void); means that f does not take any parameters.

Declaration void f(); means that function f may or may not have parameters, and if it does, we don't know what kind of parameters those are, or how many there is of them. Note that it is NOT the same as ellipsis, we can't use va_list.

Now here is where things get interesting.

Case 1

Declaration:

void f();

Definition:

void f(int a, int b, float c)
{
   //...
}

Case 2

Declaration:

void f();

Definition:

void f()
{
   //...
}

Question:

What happens at compile time in cases 1 and 2 when we call f with the correct arguments, wrong arguments and no arguments at all? What happens at run time?

Additional question:

If I declare f with arguments, but define it without them, will it make a difference? Should I be able to address the arguments from the function body?

解决方案

More terminology (C, not C++): a prototype for a function declares the types of its arguments. Otherwise the function does not have a prototype.

void f();                      // Declaration, but not a prototype
void f(void);                  // Declaration and prototype
void f(int a, int b, float c); // Declaration and prototype

Declarations that aren't prototypes are holdovers from pre-ANSI C, from the days of K&R C. The only reason to use an old-style declaration is to maintain binary compatibility with old code. For example, in Gtk 2 there is a function declaration without a prototype -- it is there by accident, but it can't be removed without breaking binaries. The C99 standard comments:

6.11.6 Function declarators

The use of function declarators with empty parentheses (not prototype-format parameter type declarators) is an obsolescent feature.

Recommendation: I suggest compiling all C code in GCC/Clang with -Wstrict-prototypes and -Wmissing-prototypes, in addition to the usual -Wall -Wextra.

What happens

void f(); // declaration
void f(int a, int b, float c) { } // ERROR

The declaration disagrees with the function body! This is actually a compile time error, and it's because you can't have a float argument in a function without a prototype. The reason you can't use a float in an unprototyped function is because when you call such a function, all of the arguments get promoted using certain default promotions. Here's a fixed example:

void f();

void g()
{
    char a;
    int b;
    float c;
    f(a, b, c);
}

In this program, a is promoted to int1 and c is promoted to double. So the definition for f() has to be:

void f(int a, int b, double c)
{
    ...
}

See C99 6.7.6 paragraph 15,

If one type has a parameter type list and the other type is specified by a function declarator that is not part of a function definition and that contains an empty identifier list, the parameter list shall not have an ellipsis terminator and the type of each parameter shall be compatible with the type that results from the application of the default argument promotions.

Answer 1

What happens at compile time in cases 1 and 2 when we call f with the correct arguments, wrong arguments and no arguments at all? What happens at run time?

When you call f(), the parameters get promoted using the default promotions. If the promoted types match the actual parameter types for f(), then all is good. If they don't match, it will probably compile but you will definitely get undefined behavior.

"Undefined behavior" is spec-speak for "we make no guarantees about what will happen." Maybe your program will crash, maybe it will work fine, maybe it will invite your in-laws over for dinner.

There are two ways to get diagnostics at compile-time. If you have a sophisticated compiler with cross-module static analysis capabilities, then you will probably get an error message. You can also get messages for un-prototyped function declarations with GCC, using -Wstrict-prototypes -- which I recommend turning on in all your projects (except for files which use Gtk 2).

Answer 2

If I declare f with arguments, but define it without them, will it make a difference? Should I be able to address the arguments from the function body?

It shouldn't compile.

Exceptions

There are actually two cases in which function arguments are allowed to disagree with the function definition.

  1. It is okay to pass char * to a function that expects void *, and vice versa.

  2. It is okay to pass a signed integer type to a function that expects the unsigned version of that type, or vice versa, as long as the value is representable in both types (i.e., it is not negative, and not out of range of the signed type).

Footnotes

1: It is possible that char promotes to unsigned int, but this is very uncommon.

这篇关于理解在C和C ++ F()和f(空隙)之间​​的差值一劳永逸的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆