void func()
实际上,空参数意味着接受任何参数。void func(void)
不接受任何争论。
但是在标准 C99 中,我发现了这样的几行:
6.7.5.3 Function declarators (including prototypes)
14 An identifier list declares only the identifiers of the parameters of the function. An empty list in a function declarator that is part of a definition of that function specifies that the function has no parameters. The empty list in a function declarator that is not part of a definition of that function specifies that no information about the number or types of the parameters is supplied.
按照标准,
func()
和 func(void)
是一样的吗?
最佳答案
TL; 博士
在声明中,
void func1(); // obsolescent
void func2(void);
行为完全不同。第一个声明了一个没有任何原型(prototype)的函数——它可以接受任意数量的参数!而后者声明了一个带有原型(prototype)的函数,它没有参数并且不接受任何参数。
在定义中
void func1() { } // obsolescent
和
void func2(void) { }
func1
没有参数和 没有原型(prototype) func2
带有原型(prototype) 没有参数。 这两者的行为截然不同,因为 C 编译器在调用带有错误数量参数的原型(prototype)函数时必须打印诊断消息,它 不需要在调用没有原型(prototype)的函数时这样做。
即,鉴于上述定义
func1(1, 2, 3); // need not produce a diagnostic message
func2(1, 2, 3); // must always produce a diagnostic message
// as it is a constraint violation
然而,这两个调用在严格遵守的程序中都是非法的,因为根据 6.5.2.2p6,它们是明确未定义的行为。 .
此外,空括号被认为是一个过时的特征:
The use of function declarators with empty parentheses (not prototype-format parameter type declarators) is an obsolescent feature.
和
The use of function definitions with separate parameter identifier and declaration lists (not prototype-format parameter type and identifier declarators) is an obsolescent feature.
详细
有两个相关但不同的概念:参数和参数。
在以下摘录中:
int foo(int n, char c) {
...
}
...
foo(42, ch);
n
和 c
是参数。 42
和 ch
是论据。引用的摘录只涉及函数的参数,但没有提及函数的原型(prototype)或参数。
声明
void func1()
表示函数 func1
可以用 调用任意数量的参数 ,即没有指定关于参数数量的信息(作为单独的声明,C99 将其指定为“没有参数指定的函数),而声明 void func2(void)
意味着函数 func2
根本不接受任何参数。您问题中的引用意味着在 内函数定义 ,
void func1()
和 void func2(void)
两者都向他们发出信号,表示没有参数,即在输入函数时设置为参数值的变量名称。 void func() {}
对比void func();
前者声明 func
确实没有参数,而后者是函数的声明 func
既没有指定参数也没有指定它们的类型(没有原型(prototype)的声明)。然而,它们在定义上有所不同,因为
void func1() {}
不声明原型(prototype),而 void func2(void) {}
确实如此,因为 ()
不是参数类型列表,而 (void)
是参数类型列表( 6.7.5.3.10 ):The special case of an unnamed parameter of type void as the only item in the list specifies that the function has no parameters.
以及 6.9.1.7
If the declarator includes a parameter type list, the list also specifies the types of all the parameters; such a declarator also serves as a function prototype for later calls to the same function in the same translation unit. If the declarator includes an identifier list, the types of the parameters shall be declared in a following declaration list. In either case, the type of each parameter is adjusted as described in 6.7.5.3 for a parameter type list; the resulting type shall be an object type.
func1
的函数定义声明符不包含 参数类型列表 ,因此该函数没有原型(prototype)。 void func1() { ... }
仍然可以使用任意数量的参数调用,而调用 void func2(void) { ... }
是编译时错误。带有任何参数(6.5.2.2):If the expression that denotes the called function has a type that includes a prototype, the number of arguments shall agree with the number of parameters. Each argument shall have a type such that its value may be assigned to an object with the unqualified version of the type of its corresponding parameter.
(强调我的)
这是一个 约束 ,根据标准,这是一个符合标准的实现 必须至少显示一条有关此问题的诊断消息。但由于
func1
没有原型(prototype),生成任何诊断不需要符合要求的实现。 但是,如果参数数量不等于参数数量,则 行为未定义 6.5.2.2p6 :
If the expression that denotes the called function has a type that does not include a prototype, [...] If the number of arguments does not equal the number of parameters, the behavior is undefined.
因此,理论上,在这种情况下,也允许符合 C99 的编译器出错或诊断警告。 StoryTeller提供证据表明clang might diagnose this ;但是,我的 GCC 似乎没有这样做(这也可能需要它与一些旧的晦涩代码兼容):
void test() { }
void test2(void) { }
int main(void) {
test(1, 2);
test2(1, 2);
}
当上面的程序用
gcc -std=c99 test.c -Wall -Werror
编译时,输出为:test.c: In function ‘main’:
test.c:7:5: error: too many arguments to function ‘test2’
test2(1, 2);
^~~~~
test.c:3:6: note: declared here
void test2(void) { }
^~~~~
也就是说,对于定义中的声明不是原型(prototype)的函数的参数(
test
),根本不会检查参数,而 GCC 认为将任何参数指定给原型(prototype)函数(test2
)是编译时错误。 );任何符合要求的实现都必须对此进行诊断,因为它违反了约束。
关于c - c99 中的 func() 与 func(void),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41803937/