如果我有这个原型:
int bar(int);
对于编译器我声明标识符bar
。
如果我有这个定义:
int bar(int a) {};
对于编译器我定义标识符bar
。
一般来说,定义会为对象进行存储分配,但是:
P.S。 关于声明或定义的C规范说明了它们相对的标识符(即标识符的声明 ...) 但是我也读过文本,其中说的是变量的声明。 那么是否存在一些差异,或者说只有一个“双向”来表达一个含义?
答案 0 :(得分:1)
函数声明可帮助编译器检查您为函数调用是否遵循相同的签名,以及返回类型,参数的数量和类型以及参数的顺序方面的语法正确性。链接器需要函数定义来交叉引用调用(使用)和定义。
当你声明一个函数时,没有分配存储,当你定义一个函数时,在可重定位的可重载地址空间上创建的函数,大小取决于函数的机器语言转换,因平台而异
答案 1 :(得分:1)
如果是函数,则在第一次调用函数时完成存储分配。定义本身不进行存储分配。
您还应注意,当函数的返回类型为void
时,使函数体为空是有效的。因此,编译器应该针对
int bar(int a) {};
[警告]控制到达非空函数的末尾[-Wreturn-type]
[警告] ISO C不允许额外的&#39 ;;'在函数之外[-pedantic]
答案 2 :(得分:1)
在C标准中,每个定义也是一个声明,而一个函数不是一个对象(我在这里提到它,因为很多人使用不同的术语,我不确定你使用哪种约定,我会使用标准的术语,因为这在SO)上是常见的。
对于标准(即在抽象机器中),函数不占用存储空间。术语“定义”在C11(n1570)6.7 p5
中定义声明指定一组标识符的解释和属性。标识符的定义是该标识符的声明: - 对于一个对象,导致为该对象保留存储; - 对于一个函数,包括函数体; *) - 对于枚举常量,是标识符的(唯一)声明; - 对于typedef名称,是标识符的第一个(或唯一)声明。 [与C99略有不同,不允许重新定义typedef]
*)函数定义具有不同的语法,如6.9.1中所述。
该标准仅在非标准部分使用术语“变量”,如脚注(作为名词;它在标准部分中用作形容词,如“可变长度数组”)。
对于术语“标识符”,请参阅同上。 6.4.2.1,
(2)标识符是一系列非数字字符(包括下划线
_
,小写和大写拉丁字母以及其他字符)和数字,它们指定6.2.1中描述的一个或多个实体
并且同上。 6.2.1 p1
标识符可以表示对象;功能;标签或结构,联合或枚举的成员;一个
typedef
名称;标签名称;一个宏名;或宏参数。相同的标识符可以表示程序中不同点的不同实体。枚举的成员称为枚举常量。此处不再考虑宏名称和宏参数,因为在程序转换的语义阶段之前,源文件中出现的任何宏名称都会被构成其宏定义的预处理标记序列替换。
为了完整起见,函数原型是一个声明;旧式声明和旧式定义是非原型声明。
答案 3 :(得分:0)
用C和C ++声明某些内容意味着什么
当你声明一个变量,一个函数,甚至一个类时,你所做的只是说:有这个名字的东西,它有这种类型。然后,编译器可以处理该名称的大多数(但不是全部)使用,而无需该名称的完整定义。声明一个值 - 没有定义它 - 允许您编写编译器可以理解的代码,而无需记录所有细节。如果您正在处理多个源文件,并且需要在多个文件中使用函数,这将特别有用。您不希望将函数体放在多个文件中,但您需要为它提供声明。
那么宣言是什么样的?例如,如果你写:
int func();
这是一个功能声明;它没有提供函数的主体,但它确实告诉编译器它可以使用这个函数并期望它将被定义在某个地方。
用C和C ++定义内容意味着什么
定义某些东西意味着提供所有必要的信息来完整地创建该东西。定义函数意味着提供函数体;定义类意味着给出类和字段的所有方法。一旦定义了某些东西,那也算作宣告它;所以你通常可以同时声明和定义一个函数,类或变量。但你没必要。
例如,对于编译器来说,声明通常是足够好的。您可以编写如下代码:
int func();
int main()
{
int x = func();
}
int func()
{
return 2;
}
由于编译器知道func的返回值以及它所采用的参数数量,因此它可以编译调用func,即使它还没有定义。实际上,方法func的定义可能会进入另一个文件!
您也可以在不定义类的情况下声明一个类
类MyClass;
需要知道MyClass中的详细信息的代码无法正常工作 - 您不能这样做:
class MyClass;
MyClass an_object;
class MyClass
{
int _a_field;
};
因为编译器需要知道变量an_object的大小,并且它不能从MyClass的声明中做到这一点;它需要下面显示的定义。