代码如下:
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);
}
编译结果:
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’
运行结果:
zbie@ubuntu:~$ ./a.out
99
10
11111110
99, 10, 11111110
我知道如果函数没有参数,代码应该没问题,比如int func(),它可以接受任何输入。但是,如何成功编译和运行这些代码呢?
发布于 2013-08-13 14:38:53
此行为是为了向后兼容旧版本的语言,即语言的K&R版本。当GCC遇到“旧风格”函数时,它符合旧的K&R C行为,在这种情况下没有任何警告。
实际上,如果您将函数更改为:int func(int param111)
,您将获得预期的警告:do:
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]
(使用GCC 4.7.3和"gcc -std=c99 -Wall x.c && ./a.out“测试)
或者引用评论中的JeremyP:“在K&R中,调用一个带有任意多个参数的函数是非常好的,因为省略符号还没有发明出来。”
请注意,编译器可以显示任意数量的额外警告,但仍然符合标准。例如,Apple的编译器会对此代码发出警告。
发布于 2013-08-13 14:50:57
函数声明被解释为K&R样式的函数声明,因为它缺少类型。在标准中,这被称为带有标识符列表的函数声明,而不是通常的声明中的参数类型列表。
根据C99规范6.9.1/7,只有具有参数类型列表的函数定义才被视为函数原型。K&R样式使用标识符列表代替,因此不被视为具有原型。
不检查对没有原型的函数的函数调用的参数数量或类型(根据6.5.2.2/8,“参数的数量和类型不与不包括函数原型声明符的函数定义中的参数的数量和类型进行比较”)。因此,使用任意数量和类型的参数调用K&R样式中声明的函数是合法的,但根据6.5.2.2/9,使用无效类型的调用将产生未定义的行为。
作为示例,以下代码将在编译时不显示任何警告(在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;
}
尽管显然有不正确的参数类型和计数。
发布于 2013-08-13 15:15:07
它被解释为K&R C,正如其他人所解释的那样。值得注意的是,这在ANSI C中是未定义的行为:
C11 6.9.1函数定义第9节
如果定义的接受可变数目参数的函数没有以省略符号结尾的参数类型列表,则行为未定义。
因此,像printf
一样,变量数自变量函数必须以...
作为参数结束
int printf( const char *format ,...);
https://stackoverflow.com/questions/18202232
复制相似问题