代码之家  ›  专栏  ›  技术社区  ›  Zifre

使用C的void参数“void foo(void)”还是不使用“void foo()”更好?[副本]

  •  268
  • Zifre  · 技术社区  · 17 年前

    void foo() 或 void foo(void) ?

    foo(bar);

    6 回复  |  直到 10 年前
        1
  •  321
  •   Daniel Earwicker    17 年前
    void foo(void);
    

    但是:

    void foo();
    

    在C和C++中意味着不同的东西!在C中,它的意思是“可以接受任何数量的未知类型的参数”,在C++中,它与 foo(void) .

    变量参数列表函数本质上是不类型安全的,应尽可能避免使用。

        2
  •  100
  •   Johannes Schaub - litb    17 年前

    void f() {
        /* do something ... */
    }
    

    这是一个参数类型列表:

    void f(void) {
        /* do something ... */
    }
    

    第一个定义了函数接受特定数量的参数,但既不传递计数,也不传递所需的类型——就像所有使用标识符列表的函数声明一样。因此,呼叫者必须事先准确知道类型和计数。因此,如果调用者调用函数并给它一些参数,则行为是未定义的。例如,堆栈可能会损坏,因为被调用的函数在获得控制权时需要不同的布局。

    不推荐在函数参数中使用标识符列表。它在过去被使用,现在仍然存在于许多生产代码中。由于这些参数升级(如果升级的参数类型与函数定义的参数类型不匹配,行为也未定义!),它们可能会造成严重的危险,当然,它们的安全性要低得多。因此,始终使用 void thingy用于没有参数的函数,仅用于函数的声明和定义。

    prototype

    第二种声明函数的方式有很多好处。当然,其中之一是检查参数的数量和类型。另一个区别是,由于编译器知道参数类型,它可以将参数的隐式转换应用于参数的类型。如果没有参数类型列表,则无法完成,参数将转换为升级类型(称为默认参数升级)。 char int 例如,当 float 将成为 double .

    void f();
    void f(int a) {
        printf("%d", a);
    }
    
    // f has now a prototype. 
    

    void f(a) 
      int a;
    { 
        printf("%d", a);
    }
    
    void f(int);
    

    第一个使用标识符列表定义函数,而第二个则使用包含参数类型列表的声明为其提供原型。

        3
  •  29
  •   Uri    10 年前

    void foo(void) 更好,因为它明确地说:不允许使用参数。

    void foo()

        4
  •  21
  •   Community Mohan Dere    9 年前

    这个答案旨在引用和解释 C99 N1256 standard draft .

    术语 声明人

    int f(int x, int y);
        ^^^^^^^^^^^^^^^
    
    int f(int x, int y) { return x + y; }
        ^^^^^^^^^^^^^^^
    
    int f();
        ^^^
    
    int f(x, y) int x; int y; { return x + y; }
        ^^^^^^^
    

    声明器是函数声明和定义的一部分。

    • 参数类型列表

    int f(int x, int y);
    

    定义如下:

    int f(int x, int y) { return x + y; }
    

    它被称为参数类型列表,因为我们必须给出每个参数的类型。

    定义如下:

    int f(x, y)
        int x;
        int y;
    { return x + y; }
    

    int g();
    

    int g(x, y);
    

    因为 6.7.5.3“函数声明器(包括原型)” 说:

    x 和 y f(x, y) 类型紧随其后。

    说:

    1使用带空括号的函数声明器(不是原型格式参数类型声明器)是一种过时的功能。

    引言 :

    在本国际标准的未来修订中撤销。它们之所以被保留,是因为

    void f();
    

    6.7.5“申报人”

    direct-declarator:
        [...]
        direct-declarator ( parameter-type-list )
        direct-declarator ( identifier-list_opt )
    

    _opt

    direct-declarator (...) 申报人的一部分。

    说:

    10 void类型的未命名参数作为列表中唯一项目的特殊情况指定该函数没有参数。

    void f(void);
    

    void

    void f(void v);
    void f(int i, void);
    void f(void, int);
    

    如果我使用f()声明会发生什么?

    6.7.5.3函数声明器(包括原型) :

    该函数的定义指定没有关于

    所以你可以逃脱惩罚:

    void f();
    void f(int x) {}
    

    void f();
    void f(float x) {}
    

    Why does an empty declaration work for definitions with int arguments but not for float arguments?

    f() {}
    

    兽医

    f(void) {}
    

    6.7.5.3函数声明器(包括原型) 说:

    这看起来与以下描述相似 f(void) .

    int f() { return 0; }
    int main(void) { f(1); }
    

    int f(void) { return 0; }
    int main(void) { f(1); }
    

    不符合以下讨论的要求: Why does gcc allow arguments to be passed to a function defined to be with no arguments?

        5
  •  10
  •   maja    6 年前

    除了句法差异,许多人还喜欢使用 void function(void)

    如果你正在使用搜索功能,并想找到该功能的实现,你可以搜索 function(void)

    void ,你必须搜索 function() 因此也会找到所有函数调用,这使得找到实际实现变得更加困难。

        6
  •  9
  •   Peter Mortensen Pieter Jan Bonestroo    4 年前

    在C++中,有 main() 和 main(void) .

    main() 参数数量。

    例子:

    main (){
        main(10, "abc", 12.28);
        // Works fine!
        // It won't give the error. The code will compile successfully.
        // (May cause a segmentation fault when run)
    }
    

    将被调用 任何参数。如果我们试图传递它,那么这最终会导致编译器错误。

    例子:

    main (void) {
         main(10, "abc", 12.13);
         // This throws "error: too many arguments to function ‘main’ "
    }
    
    推荐文章