Adm*_*onB 385 c parameters function-parameter function-prototypes
我刚刚遇到某人的C代码,我很困惑为什么要编译.有两点我不明白.
首先,与实际函数定义相比,函数原型没有参数.其次,函数定义中的参数没有类型.
#include <stdio.h>
int func();
int func(param)
{
return param;
}
int main()
{
int bla = func(10);
printf("%d", bla);
}
Run Code Online (Sandbox Code Playgroud)
为什么这样做?我已经在几个编译器中测试过,它运行正常.
Kri*_*dra 270
所有其他答案都是正确的,但只是为了完成
函数以下列方式声明:
Run Code Online (Sandbox Code Playgroud)return-type function-name(parameter-list,...) { body... }
return-type是函数返回的变量类型.这不能是数组类型或函数类型.如果没有给出,则假定为int.
function-name是函数的名称.
parameter-list是函数用逗号分隔的参数列表.如果没有给出参数,则该函数不带任何参数,并且应该用空的括号或用关键字void定义.如果参数列表中的变量前面没有变量类型,则假定为int.数组和函数不会传递给函数,但会自动转换为指针.如果列表以省略号(,...)结束,则没有设定数量的参数.注意:标头stdarg.h可用于在使用省略号时访问参数.
再次为了完整起见.从C11规范6:11:6(第179页)
的使用功能与空括号声明符(未原型格式参数类型说明符)是一个过时特征.
Ton*_*ion 158
在C中func()
意味着您可以传递任意数量的参数.如果你不需要参数,那么你必须声明为func(void)
.您传递给函数的类型,如果未指定,则默认为int
.
Jen*_*ens 57
int func();
从没有C标准的日子开始,这是一个过时的功能声明,即K&R C的日子(1989年之前,第一个"ANSI C"标准发布的那一年).
请记住,K&R C中没有原型,关键字void
尚未发明.您所能做的就是告诉编译器函数的返回类型.K&R C中的空参数列表表示"未指定但固定"的参数数量.固定意味着您必须每次都使用相同数量的args 调用该函数(与可变参数函数相反,例如printf
,每次调用的数字和类型可能不同).
许多编译器会诊断出这个结构; 特别gcc -Wstrict-prototypes
会告诉你"函数声明不是原型",这是一个现场,因为它看起来像一个原型(特别是如果你被C++中毒!),但事实并非如此.这是一种旧式的K&R C返回型声明.
经验法则:永远不要将空参数列表声明留空,用于int func(void)
具体.这将K&R返回类型声明转换为适当的C89原型.编译器很高兴,开发人员很高兴,静态的跳棋很开心.那些被C++误导的人可能会感到畏缩,因为他们在尝试锻炼外语时需要输入额外的字符:-)
Lei*_*Mou 30
它是K&R风格的功能声明和定义.来自C99标准(ISO/IEC 9899:TC3)
第6.7.5.3节函数声明符(包括原型)
标识符列表仅声明函数参数的标识符.函数声明符中的空列表是该函数定义的一部分,指定该函数没有参数.函数声明符中的空列表不是该函数定义的一部分,它指定不提供有关参数数量或类型的信息.(如果两种函数类型都是"旧样式",则不会比较参数类型.)
第6.11.6节函数声明符
使用带有空括号的函数声明符(不是prototype-format参数类型声明符)是一个过时的功能.
第6.11.7节函数定义
使用具有单独的参数标识符和声明列表(而不是原型格式参数类型和标识符声明符)的函数定义是一个过时的功能.
哪种旧式意味着K&R风格
例:
宣言: int old_style();
定义:
int old_style(a, b)
int a;
int b;
{
/* something to do */
}
Run Code Online (Sandbox Code Playgroud)
Shi*_*dim 15
int
如果函数返回类型和参数列表中没有给出类型,则C假定.只有这个规则才能实现奇怪的事情.
函数定义如下所示.
int func(int param) { /* body */}
Run Code Online (Sandbox Code Playgroud)
如果它是你写的原型
int func(int param);
Run Code Online (Sandbox Code Playgroud)
在原型中,您只能指定参数的类型.参数名称不是必需的.所以
int func(int);
Run Code Online (Sandbox Code Playgroud)
此外,如果您不指定参数类型,但将名称int
假定为类型.
int func(param);
Run Code Online (Sandbox Code Playgroud)
如果你走得更远,下面的工作也是如此.
func();
Run Code Online (Sandbox Code Playgroud)
编译器假定int func()
你写的时候func()
.但是不要放入func()
功能体内.这将是一个函数调用
RTO*_*kit 11
正如@Krishnabhadra所述,之前所有其他用户的回复都有正确的解释,我只想对某些要点进行更详细的分析.
在旧C中,如ANSI-C中的" 无类型形式参数 ",取8位MPU中的工作寄存器或指令深度能力(影子寄存器或指令累积周期)的尺寸,将是16位,16位MPU等将是一个int16,在这种情况下,64位架构可能会选择编译选项,如:-m32.
虽然在高级别上看起来似乎更简单,但是为了传递多个参数,程序员在控制维数数据类型步骤中的工作变得更加苛刻.
在其他情况下,对于某些微处理器体系结构,ANSI编译器定制,利用这些旧功能中的一些来优化代码的使用,迫使这些"无类型的形式参数"的位置在工作寄存器内部或外部工作,今天你得到使用"volatile"和"register"几乎相同.
但应该指出的是,最现代的编译器,没有对两种类型的参数声明做任何区分.
在linux下使用gcc进行编译的示例:
在任何情况下,本地原型的声明都是没有用的,因为没有参数的调用没有参考这个原型会被忽略.如果将系统与"无类型形式参数"一起使用,则对于外部调用,请继续生成声明性原型数据类型.
像这样:
int myfunc(int param);
Run Code Online (Sandbox Code Playgroud)
关于参数类型,这里已经有正确的答案,但如果你想从编译器中听到它,你可以尝试添加一些标志(标志几乎总是一个好主意).
使用gcc foo.c -Wextra
我得到的程序编译你的程序:
foo.c: In function ‘func’:
foo.c:5:5: warning: type of ‘param’ defaults to ‘int’ [-Wmissing-parameter-type]
Run Code Online (Sandbox Code Playgroud)
奇怪的-Wextra
是没有抓住这个clang
(-Wmissing-parameter-type
因为某种原因不能识别,可能是上面提到的历史),但-pedantic
确实如此:
foo.c:5:10: warning: parameter 'param' was not declared,
defaulting to type 'int' [-pedantic]
int func(param)
^
1 warning generated.
Run Code Online (Sandbox Code Playgroud)
并且对于原型问题,如上所述再次int func()
引用任意参数,除非您明确地将其定义为int func(void)
然后会按预期给出错误:
foo.c: In function ‘func’:
foo.c:6:1: error: number of arguments doesn’t match prototype
foo.c:3:5: error: prototype declaration
foo.c: In function ‘main’:
foo.c:12:5: error: too many arguments to function ‘func’
foo.c:5:5: note: declared here
Run Code Online (Sandbox Code Playgroud)
或者在clang
:
foo.c:5:5: error: conflicting types for 'func'
int func(param)
^
foo.c:3:5: note: previous declaration is here
int func(void);
^
foo.c:12:20: error: too many arguments to function call, expected 0, have 1
int bla = func(10);
~~~~ ^~
foo.c:3:1: note: 'func' declared here
int func(void);
^
2 errors generated.
Run Code Online (Sandbox Code Playgroud)