声明和原型的区别

9 c declaration language-lawyer function-prototypes

C语句中的声明和原型有什么区别?在哪些情况下,它们被称为声明和原型?

Sou*_*osh 9

TL; DR; 所有原型都是声明,但并非所有声明都是原型.

声明是标准中使用的通用术语,原型更具体.

引用C11,第§6.7章

声明指定一组标识符的解释和属性.[...]

从§6.7.6开始,

每个声明符声明一个标识符,并声明当与表达式中出现的声明符形式相同的操作数出现在表达式中时,它指定一个函数或对象,其范围,存储持续时间和声明说明符指示的类型.

另一方面,从章节6.2.1开始

[....] 函数原型是声明其参数类型的函数的声明.

所以,一个班轮,原型是更完整的形式(包括参数类型)的声明.


关于"标识符":章节§6.4.2.1,

标识符是一系列非数字字符(包括下划线_,小写和大写拉丁字母以及其他字符)和数字,它们指定6.2.1中描述的一个或多个实体.[...]

在章节§6.2.1中,

标识符可以表示对象; 功能; 标签或结构,联合或枚举的成员; 一个typedef名称; 标签名称; 一个宏名; 或宏参数.[....]


Ker*_* SB 8

声明引入了一个名称:

int a;    // "a" has type int
Run Code Online (Sandbox Code Playgroud)

函数声明(也不是原型)只引入函数的名称及其返回类型:

int f();   // a function call expression "f(x, y, ...)" has type int
Run Code Online (Sandbox Code Playgroud)

但是,这样的函数声明没有指定哪些参数对函数调用有效; 换句话说,它没有指定功能签名.这是由函数原型(这是一种声明)完成的:

int g1(void);         // "g1" takes no arguments, "g()" has type int
int g2(float, char);  // "g2" takes two arguments
int g3(int, ...);     // "g3" takes at least one argument
Run Code Online (Sandbox Code Playgroud)

函数原型在函数调用时是否可见会对调用参数产生重要影响:如果没有原型可见,则所有参数都会进行默认参数提升.相比之下,如果原型可用,则函数参数将转换为相应形式参数的类型(如果参数数量不匹配或任何转换形式不正确,则程序格式错误) .

为了进一步探讨这一点,请注意存在某些"不可能"的组合:如果我们有一个声明int g2();和一个定义int g2(float, char) { return 0; },那么永远不可能g2只使用声明来调用,因为形式参数类型不能由默认参数提升产生.通常建议始终使用原型声明,而不要使用非原型声明.

最后,如果原型以省略号(...)结尾,则可以使用比参数更多的参数调用原型函数.使用<stdarg.h>获取这些参数要求在调用这样的变量参数函数时可以看到函数原型.

  • 原型也是一种宣言. (3认同)

Lun*_*din 6

  • 一个函数声明为任何形式的行声明一个函数,结束时用的;

  • 原型是一个函数声明,其中被指定的所有类型的参数。

示例,原型函数声明:void func (void);
示例,非原型函数声明:void func ();.

非原型函数声明是一个过时的特性 (6.11.6),可能会从 C 语言中删除。因此,您应该始终使用原型格式,而不要使用其他任何格式。


Vla*_*cow 5

根据 C 标准(6.2.1 identi\xef\xac\x81ers 的范围)

\n\n
\n
    \n
  1. ...(函数原型是函数的声明,该函数声明其参数的 \n 类型。)
  2. \n
\n
\n\n

即原型提供了有关函数参数类型的信息。

\n\n

例如考虑

\n\n
void f();\n
Run Code Online (Sandbox Code Playgroud)\n\n

\n\n
void f( void );\n
Run Code Online (Sandbox Code Playgroud)\n\n

第一个声明不是原型,因为对函数参数一无所知。

\n\n

第二个声明是原型,因为它提供了函数参数的类型列表(它是一种特殊的类型列表,speci\xef\xac\x81es 该函数没有参数)。

\n