且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

C 函数中未指定数量的参数 - void foo()

更新时间:2023-12-01 07:49:57

这是一个老式函数声明.

本声明:

void foo();

声明 foo 是一个返回 void 的函数,它接受一个未指定但固定数量和类型的参数.这并不意味着带有任意参数的调用是有效的;这意味着编译器无法使用错误数量或类型的参数诊断错误调用.

declares that foo is a function returning void that takes an unspecified but fixed number and type(s) of arguments. It doesn't mean that calls with arbitrary arguments are valid; it means that the compiler can't diagnose incorrect calls with the wrong number or type of arguments.

某处,也许在另一个翻译单元(源文件)中,必须有函数的定义,也许:

Somewhere, perhaps in another translation unit (source file), there has to be a definition of the function, perhaps:

void foo(x, y)
long x;
double *y;
{
    /* ... */
}

这意味着对 foo 的任何调用不会传递两个 longdouble* 类型的参数> 无效,并且具有未定义的行为.

This means that any call to foo that doesn't pass two arguments of type long and double* is invalid, and has undefined behavior.

在 1989 ANSI C 标准之前,这些是该语言中唯一可用的函数声明和定义类型,编写正确函数调用的负担完全由程序员承担.ANSI C 添加了原型,即指定函数参数类型的函数声明,允许在编译时检查函数调用.(这个特性是从早期的 C++ 中借来的.)上面的现代等价物是:

Prior to the 1989 ANSI C standard, these were the only kind of function declaration and definition available in the language, and the burden of writing correct function calls was entirely on the programmer. ANSI C added prototypes, function declarations that specify the types of a function's parameters, which allow compile-time checking of function calls. (This feature was borrowed from early C++.) The modern equivalent of the above would be:

void foo(long x, double *y);

/* ... */

void foo(long x, double *y) {
    /* ... */
}

旧式(非原型)声明和定义仍然合法,但它们正式过时,这意味着,原则上,它们可以从语言的未来版本中删除-- 尽管它们仍然存在于 2011 年标准中,但我不知道这是否会真正发生.

Old-style (non-prototype) declarations and definitions are still legal, but they're officially obsolescent, which means that, in principle, they could be removed from a future version of the language -- though since they're still around in the 2011 standard I don't know that that will ever actually happen.

没有充分的理由在现代 C 代码中使用旧式函数声明和定义.(我已经看到在某些极端情况下使用它们的论据,但我发现它们没有说服力.)

There is no good reason to use old-style function declarations and definitions in modern C code. (I've seen arguments for using them in some corner cases, but I find them unconvincing.)

C 还支持 variadic 函数,如 printf,它接受任意数量的参数,但这是一个独特的特性.可变参数函数必须用原型声明,其中包括尾随的 , ....(调用没有可见原型的可变参数函数并不违法,但它具有未定义的行为.)该函数本身使用 中定义的宏来处理其参数.与旧式函数声明一样,没有编译时检查对应于 , ... 的参数(尽管一些编译器可能会检查一些调用;例如 gcc 会警告 , ... 中的参数code>printf 调用与格式字符串不一致).

C also supports variadic functions like printf, which do take an arbitrary number of arguments, but that's a distinct feature. A variadic function must be declared with a prototype, which includes a trailing , .... (Calling a variadic function with no visible prototype isn't illegal, but it has undefined behavior.) The function itself uses macros defined in <stdarg.h> to process its parameters. As with old-style function declarations, there is no compile-time checking for arguments corresponding to the , ... (though some compilers may check some calls; for example gcc warns if the arguments in a printf call are inconsistent with the format string).