代码如下:
int func(param111)
{
printf("%d\n", param111);
return param111;
}
int main()
{
int bla0 = func(99);
int bla1 = func(10,99);
int bla2 = func(11111110,99,10001);
printf("%d, %d, %d\n", bla0, bla1, bla2);
}
Run Code Online (Sandbox Code Playgroud)
编译结果:
zbie@ubuntu:~$ gcc -Wall -g -std=c99 -O2 zeroparam.c
zeroparam.c: In function ‘func’:
zeroparam.c:2: warning: type of ‘param111’ defaults to ‘int’
Run Code Online (Sandbox Code Playgroud)
运行结果:
zbie@ubuntu:~$ ./a.out
99
10
11111110
99, 10, 11111110
Run Code Online (Sandbox Code Playgroud)
我知道如果带有零参数的func,例如int func()接受任何输入,代码应该没问题.但是这个代码如何编译并成功运行?
Pro*_*ica 19
此行为是为了向后兼容该语言的旧版本,即该语言的K&R版本.当GCC遇到"旧式"功能时,它符合旧的K&R C行为,这意味着在这种情况下没有警告.
事实上,如果你改变的功能:int func(int param111)
你做得到预期的警告:
x.c: In function ‘main’:
x.c:11:5: error: too many arguments to function ‘func’
x.c:2:5: note: declared here
x.c:12:5: error: too many arguments to function ‘func’
x.c:2:5: note: declared here
x.c:14:1: warning: control reaches end of non-void function [-Wreturn-type]
Run Code Online (Sandbox Code Playgroud)
(经GCC 4.7.3和"gcc -std = c99 -Wall xc && ./a.out"测试)
或者从评论中引用JeremyP:"在K&R C中,使用尽可能多的参数来调用函数是完全没问题的,因为省略符号当时并未被发明." .
请注意,编译器可以显示它想要的额外警告,并且仍然符合标准.例如Apple的编译器警告这个代码.
函数声明被解释为K&R样式函数声明,因为它缺少类型.在标准中,这称为带有标识符列表的函数声明,而不是通常声明中的参数类型列表.
根据C99规范6.9.1/7,只有具有参数类型列表的函数定义被认为是函数原型.K&R样式使用标识符列表,因此不被认为具有原型.
不检查没有原型的函数的函数调用是否参数计数或类型(根据6.5.2.2/8,"参数的数量和类型与不包含函数原型声明符的函数定义中的参数的数量和类型不进行比较" ).因此,使用任何数量和类型的参数调用在K&R样式中声明的函数是合法的,但是对于6.5.2.2/9,使用无效类型的调用将产生未定义的行为.
作为示例,以下将编译而没有任何警告(on gcc -Wall -Wextra -pedantic -std=c99 -O
):
#include <stdio.h>
void *func(param111)
char *param111;
{
printf("%s\n", param111);
return param111;
}
int main()
{
void *bla0 = func();
void *bla1 = func(99);
void *bla2 = func(11111110,99);
printf("%p, %p, %p\n", bla0, bla1, bla2);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
尽管显然有不正确的参数类型和计数.