两者的含义使我难以理解。


#1楼

经验法则:

  • 声明告诉编译器如何解释内存中变量的数据。 每次访问都需要这样做。

  • 定义保留内存以使变量存在。 必须在第一次访问之前进行一次。


#2楼

从wiki.answers.com:

术语声明(在C语言中)表示您正在告诉编译器有关类型,大小的信息,如果是函数声明,则是告诉程序的任何变量的参数的类型和大小,或用户定义的程序类型或函数。 没有足够的空间被保留在内存中声明的情况下,任何变量。 但是,编译器知道在创建此类型的变量的情况下要保留多少空间。

例如,以下是所有声明:

extern int a;
struct _tagExample { int a; int b; };
int myFunc (int a, int b);

另一方面,定义意味着除了声明所做的所有事情之外,空间还保留在内存中。 您可以说“ DEFINITION = DECLARATION + SPACE RESERVATION”是以下定义示例:

int a;
int b = 0;
int myFunc (int a, int b) { return a + b; }
struct _tagExample example;

参见答案 。


#3楼

宣言

声明告诉编译器程序元素或名称存在。 声明将一个或多个名称引入程序。 声明可以在程序中多次出现。 因此,可以为每个编译单元声明类,结构,枚举类型和其他用户定义的类型。

定义

定义指定名称描述的代码或数据。 必须先声明一个名称,然后才能使用它。


#4楼

声明引入一个标识符并描述其类型,可以是类型,对象或函数。 声明是编译器需要接受对该标识符的引用的内容。 这些是声明:

extern int bar;
extern int g(int, int);
double f(int, double); // extern can be omitted for function declarations
class foo; // no extern allowed for type declarations

定义实际上实例化/实现了该标识符。 这是链接器将链接引用链接到那些实体所需要的。 这些是与上述声明相对应的定义:

int bar;
int g(int lhs, int rhs) {return lhs*rhs;}
double f(int i, double d) {return i+d;}
class foo {};

可以在定义的地方使用定义。

可以根据需要多次声明标识符。 因此,以下内容在C和C ++中是合法的:

double f(int, double);
double f(int, double);
extern double f(int, double); // the same as the two above
extern double f(int, double);

但是,必须定义一次。 如果忘记定义已在某处声明和引用的内容,则链接器将不知道将引用链接到什么内容,并且会抱怨缺少符号。 如果定义不止一次,则链接器将不知道要将引用链接到哪个定义中,并抱怨重复的符号。


由于关于C ++中的类声明和类定义的争论不断(在回答和其他问题的注释中)不断出现,因此我将在此处粘贴C ++标准的引号。
在3.1 / 2,C ++ 03表示:

声明是定义,除非它是类名声明。

3.1 / 3然后给出一些例子。 其中:

[Example: [...]
struct S { int a; int b; }; // defines S, S::a, and S::b [...]
struct S; // declares S
—end example

概括起来:C ++标准考虑struct x; 成为声明struct x {}; 一个定义 。 (换句话说, “前向声明”是不正确的用词 ,因为C ++中没有其他形式的类声明。)

感谢litb(Johannes Schaub)在他的答案之一中挖掘了实际的章节。


#5楼

从C ++标准第3.1节开始:

声明将名称引入翻译单元中,或重新声明由先前声明引入的名称。 声明指定这些名称的解释和属性。

下一段指出(强调我的意思)声明是一个定义,除非...

...它在不指定函数主体的情况下声明了一个函数:

void sqrt(double);  // declares sqrt

...它在类定义中声明了一个静态成员:

struct X
{int a;         // defines astatic int b;  // declares b
};

...它声明了一个类名:

class Y;

...它包含extern关键字,但没有初始化程序或函数体:

extern const int i = 0;  // defines i
extern int j;  // declares j
extern "C"
{void foo();  // declares foo
}

...或者是typedefusing语句。

typedef long LONG_32;  // declares LONG_32
using namespace std;   // declares std

现在,出于重要原因,理解声明和定义之间的区别非常重要:“ 一个定义规则” 。 从C ++标准的3.2.1节开始:

任何变量,函数,类类型,枚举类型或模板的翻译单元均不得包含一个以上的定义。


#6楼

根据C99标准6.7(5):

声明指定一组标识符的解释和属性。 标识符的定义是对该标识符的声明:

  • 对于一个对象,导致为该对象保留存储;
  • 对于功能,包括功能主体;
  • 对于枚举常量或typedef名称,是标识符的(唯一)声明。

根据C ++标准3.1(2):

声明是一个定义,除非它在不指定函数主体的情况下声明函数,它包含extern说明符或链接规范,并且既不是初始化程序也不是函数体,它在类声明中声明静态数据成员,它是一个类名声明,或者是typedef声明,using-声明或using-伪指令。

然后有一些例子。

有趣的是(或者不是,但是我对此有些惊讶), typedef int myint; 是C99中的定义,但仅是C ++中的声明。


#7楼

您能否用最笼统的术语陈述一下,即声明是没有分配存储空间的标识符,而定义实际上是根据声明的标识符分配存储空间的?

一个有趣的想法-模板在类或函数与类型信息链接之前无法分配存储。 那么模板标识符是声明还是定义? 由于未分配存储空间,因此应该是一个声明,而您只是在“模板化”模板类或函数的原型。


#8楼

在C ++中有一些有趣的极端情况(在C中也有一些)。 考虑

T t;

这可以是定义或声明,具体取决于T是什么类型:

typedef void T();
T t; // declaration of function "t"struct X { T t; // declaration of function "t".
};typedef int T;
T t; // definition of object "t".

在C ++中,使用模板时,还有另一种情况。

template <typename T>
struct X { static int member; // declaration
};template<typename T>
int X<T>::member; // definitiontemplate<>
int X<bool>::member; // declaration!

最后的声明不是定义。 这是X<bool>的静态成员的显式专业化的声明。 它告诉编译器:“如果要实例化X<bool>::member ,则不要从主模板实例化该成员的定义,而要使用在其他地方找到的定义”。 要定义它,您必须提供一个初始化程序

template<>
int X<bool>::member = 1; // definition, belongs into a .cpp file.

#9楼

声明:“在某个地方,存在一个foo。”

定义:“ ...就在这里!”


#10楼

声明是指为变量指定名称和类型(在变量声明的情况下),例如:

int i;

或为没有主体的函数提供名称,返回类型和参数类型(在函数声明的情况下),例如:

int max(int, int);

而定义是指为变量赋值(在变量定义的情况下),例如:

i = 20;

或向功能提供/添加主体(功能)称为功能定义,例如:

int max(int a, int b)
{if(a>b)   return a;return b;
}

许多时间的声明和定义可以一起完成:

int i=20;

和:

int max(int a, int b)
{if(a>b)   return a;return b;
}

在上述情况下,我们定义并声明变量ifunction max()


#11楼

C ++ 11更新

由于我看不到与C ++ 11相关的答案,所以这里是一个。

声明是定义,除非声明a / n:

  • 不透明枚举- enum X : int;
  • 模板参数- T的template<typename T> class MyArray;
  • 参数声明-int中的xy int add(int x, int y);
  • 别名声明- using IntVector = std::vector<int>;
  • 静态断言声明static_assert(sizeof(int) == 4, "Yikes!")
  • 属性声明(实现定义)
  • 空声明;

上面的列表从C ++ 03继承的其他子句:

  • 函数声明- 添加 int add(int x, int y);
  • 包含声明或链接说明符的extern int a;说明符extern int a;extern "C" { ... };
  • 在一个类的静态数据成员- Xclass C { static int x; }; class C { static int x; };
  • 类/结构声明- struct Point;
  • typedef声明typedef int Int;
  • 使用声明- using std::cout;
  • using指令- using namespace NS;

模板声明是声明。 如果模板声明定义了函数,类或静态数据成员,则它也是定义。

我发现从标准中区分声明和定义的示例有助于我理解它们之间的细微差别:

// except one all these are definitions
int a;                                  // defines a
extern const int c = 1;                 // defines c
int f(int x) { return x + a; }          // defines f and defines x
struct S { int a; int b; };             // defines S, S::a, and S::b
struct X {                              // defines Xint x;                              // defines non-static data member xstatic int y;                       // DECLARES static data member yX(): x(0) { }                       // defines a constructor of X
};
int X::y = 1;                           // defines X::y
enum { up , down };                     // defines up and down
namespace N { int d; }                  // defines N and N::d
namespace N1 = N;                       // defines N1
X anX;                                  // defines anX// all these are declarations
extern int a;                           // declares a
extern const int c;                     // declares c
int f(int);                             // declares f
struct S;                               // declares S
typedef int Int;                        // declares Int
extern X anotherX;                      // declares anotherX
using N::d;                             // declares N::d// specific to C++11 - these are not from the standard
enum X : int;                           // declares X with int as the underlying type
using IntVector = std::vector<int>;     // declares IntVector as an alias to std::vector<int>
static_assert(X::y == 1, "Oops!");      // declares a static_assert which can render the program ill-formed or have no effect like an empty declaration, depending on the result of expr
template <class T> class C;             // declares template class C
;                                       // declares nothing

#12楼

这听起来似乎很俗气,但这是我一直保持直觉的最好方式:

声明:图片Thomas Jefferson发表讲话……“我在此声明此源代码中存在该FOO!”

定义:想象一本字典,您正在查找Foo及其实际含义。


#13楼

在此处找到类似的答案: C中的技术面试问题 。

声明为程序提供了名称; 定义提供了程序中实体(例如类型,实例和功能)的唯一描述。 声明可以在给定范围内重复,它在给定范围内引入名称。

声明是一个定义,除非:

  • 声明在不指定函数体的情况下声明了一个函数,
  • 声明包含一个外部说明符,没有初始化器或函数体,
  • 声明是没有类定义的静态类数据成员的声明,
  • 声明是一个类名定义,

定义是声明,除非:

  • 定义定义一个静态类数据成员,
  • 定义定义非内联成员函数。

#14楼

使用extern存储类时,声明和定义的概念将成为一个陷阱,因为定义将位于其他位置,并且您在本地代码文件(页面)中声明变量。 C和C ++之间的区别是,在C中,声明通常在函数或代码页的开头进行。 在C ++中不是那样。 您可以在自己选择的地方进行申报。


#15楼

我最喜欢的示例是“ int Num = 5”,这里您的变量是1.定义为int 2.声明为Num,并且3.实例化为5。 我们

  • 定义对象的类型,它可以是内置的,也可以是类或结构。
  • 声明一个对象的名称,因此已经声明了具有名称的任何内容,包括变量,函数等。

类或结构允许您更改以后使用对象时定义对象的方式。 例如

  • 可以声明一个没有明确定义的异构变量或数组。
  • 使用C ++中的偏移量,您可以定义一个没有声明名称的对象。

当我们学习编程时,这两个术语经常会混淆,因为我们经常同时做这两个事情。


#16楼

宣言 :

int a; // this declares the variable 'a' which is of type 'int'

因此,声明将变量与类型相关联。

以下是一些声明示例。

int a;
float b;
double c;

现在函数声明:

int fun(int a,int b);

注意函数末尾的分号,因此它说这只是一个声明。 编译器知道,程序中的某个位置将使用该原型定义功能。 现在,如果编译器得到函数调用,则如下所示

int b=fun(x,y,z);

编译器将抛出一个错误,指出没有该函数。 因为它没有该功能的任何原型。

注意两个程序之间的区别。

程序1

#include <stdio.h>
void print(int a)
{printf("%d",a);
}
main()
{print(5);
}

在此,还将声明和定义打印功能。 由于函数调用是在定义之后进行的。 现在看下一个程序。

程序2

 #include <stdio.h>void print(int a); // In this case this is essentialmain(){print(5);}void print(int a){printf("%d",a);}

这一点很重要,因为函数调用先于定义,因此编译器必须知道是否存在任何此类函数。 因此,我们声明了将通知编译器的函数。

定义:

定义函数的这一部分称为“定义”。 它说明了该函数内部的操作。

void print(int a)
{printf("%d",a);
}

现在有了变量。

int a; //declaration
a=10; //definition

有时,这样的声明和定义被分组为单个语句。

int a=10;

#17楼

声明为编译器提供了符号名称。 定义是为符号分配空间的声明。

int f(int x); // function declaration (I know f exists)int f(int x) { return 2*x; } // declaration and definition

#18楼

定义表示实际编写的函数,声明表示简单的声明函数,例如

void  myfunction(); //this is simple declaration

void myfunction()
{some statement;
}

这是功能myfunction的定义


#19楼

要了解声明和定义之间的区别,我们需要查看汇编代码:

uint8_t   ui8 = 5;  |   movb    $0x5,-0x45(%rbp)
int         i = 5;  |   movl    $0x5,-0x3c(%rbp)
uint32_t ui32 = 5;  |   movl    $0x5,-0x38(%rbp)
uint64_t ui64 = 5;  |   movq    $0x5,-0x10(%rbp)
double   doub = 5;  |   movsd   0x328(%rip),%xmm0        # 0x400a20movsd   %xmm0,-0x8(%rbp)

这仅仅是定义:

ui8 = 5;   |   movb    $0x5,-0x45(%rbp)
i = 5;     |   movl    $0x5,-0x3c(%rbp)
ui32 = 5;  |   movl    $0x5,-0x38(%rbp)
ui64 = 5;  |   movq    $0x5,-0x10(%rbp)
doub = 5;  |   movsd   0x328(%rip),%xmm0        # 0x400a20movsd   %xmm0,-0x8(%rbp)

如您所见,没有任何变化。

声明与定义不同,因为声明仅提供编译器使用的信息。 例如,uint8_t告诉编译器使用asm函数movb。

看到:

uint def;                  |  no instructions
printf("some stuff...");   |  [...] callq   0x400450 <printf@plt>
def=5;                     |  movb    $0x5,-0x45(%rbp)

声明没有等效的指令,因为它没有要执行的内容。

此外,声明告诉编译器变量的范围。

可以说,声明是编译器用来建立变量的正确用法以及某些内存属于某个变量的时间的信息。


#20楼

要理解名词,让我们先关注动词。

宣布 -正式宣布; 宣布

定义 -清晰,完整地显示或描述(某人或某物)

因此,当您声明某物时,您只需告诉它是什么

// declaration
int sum(int, int);

这行代码声明一个名为sum的C函数,该函数接受两个int类型的参数并返回一个int 。 但是,您还不能使用它。

当您提供它的实际工作原理时 ,这就是它的定义。

// definition
int sum(int x, int y)
{return x + y;
}

#21楼

根据GNU C库手册( http://www.gnu.org/software/libc/manual/html_node/Header-Files.html )

在C语言中,声明仅提供有关函数或变量存在并给出其类型的信息。 对于函数声明,可能还会提供有关其参数类型的信息。 声明的目的是允许编译器正确处理对声明的变量和函数的引用。 另一方面,定义实际上是为变量分配存储空间或说明函数的功能。


#22楼

可执行文件生成的阶段:

(1)预处理器->(2)转换器/编译器->(3)链接器

在第2阶段(翻译器/编译器)中,代码中的声明语句告诉编译器我们将来将要使用的这些东西,您以后可以找到定义,其含义是:

翻译人员要确保: 什么是? 手段申报

(3)阶段(链接器)需要定义绑定事物

链接器确保: 哪里是什么? 手段定义


#23楼

K&R(第二版)中散布着一些非常清晰的定义。 它有助于将它们放在一个地方并作为一个地方阅读:

“定义”是指创建或分配变量的位置; “声明”是指声明变量性质但未分配存储空间的地方。 [p。 33]

...

区分外部变量的声明及其定义很重要。 声明声明变量的属性(主要是其类型); 定义也会导致存储被搁置。 如果线路

 int sp; double val[MAXVAL] 

出现在任何函数之外,它们定义了外部变量spval ,导致存储被搁置,并且还充当该源文件其余部分的声明。

另一方面,线条

 extern int sp; extern double val[]; 

对于源文件的其余部分,请声明 sp是一个int ,而val是一个double val数组(其大小由其他位置确定),但它们不会为它们创建变量或保留存储空间。

在组成源程序的所有文件中,外部变量的定义必须只有一个。 ...数组大小必须使用定义指定,但在extern声明中是可选的。 [pp。 80-81]

...

声明指定对每个标识符的解释; 它们不一定保留与标识符关联的存储。 保留存储的声明称为定义 。 [p。 210]

定义和声明之间有什么区别?相关推荐

  1. 变量定义和声明的区别~~~概念上千万不要栽跟头!!!

    变量的声明有两种情况: 1.一种是需要建立存储空间的.例如:int a 在声明的时候就已经建立了存储空间. 2.另一种是不需要建立存储空间的. 例如:extern int a 其中变量a是在别的文件中 ...

  2. 变量定义和声明的区别(整理)

    变量的声明有两种情况: 1.一种是需要建立存储空间的.例如:int a 在声明的时候就已经建立了存储空间. 2.另一种是不需要建立存储空间的. 例如:extern int a 其中变量a是在别的文件中 ...

  3. C++ 笔记(05)— 变量(变量定义、声明、初始化、extern关键字、变量之间转换)

    1. 变量定义 变量定义就是告诉编译器在何处创建变量的存储,以及如何创建变量的存储.变量定义指定一个数据类型,并包含了该类型的一个或多个变量的列表,如下所示: type variable_list; ...

  4. JS基础篇--函数声明与定义,作用域,函数声明与表达式的区别

    Scoping & Hoisting 例: var a = 1;function foo() {if (!a) {var a = 2;}alert(a); };foo(); 上面这段代码在运行 ...

  5. c语言变量申明和定义区别,C语言中变量定义与声明的区别

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 在程序设计中,时时刻刻都用到变量的定义和变量的声明,可有些时候我们对这个概念不是很清楚,知道它是怎么用,但却不知是怎么一会事,下面我就简单的把他们的区别介 ...

  6. 十:变量的定义和声明的区别?

    1. 变量的声明: 声明是用来告诉编译器变量的名称和类型,而不分配内存. 变量的声明有两重含义: 告诉编译器,这个名字已经匹配到一块内存上,下面的代码用到变量或者对象是在别的地方定义的.声明可以出现多 ...

  7. C语言-定义和声明的区别

    3.定义与声明 定义:在内存中开辟空间(只能有一次),用来保存数据 声明:告知 (可以声明多次) 3.1.什么是变量 在内存中开辟特定大小的空间,用来保存数据 3.2.如何定义变量-怎么用 int x ...

  8. C++/C中定义与声明的区别

    在C++/C中,定义与声明是不一样的,主要区别在于是否分配了内存. 定义:编译器创建一个对象,为该对象分配一块内存,并为该内存起一个名字,这个名字就叫变量名. 例如: int a;//未初始化 int ...

  9. Builder Design模式和Factory Design模式之间有什么区别?

    Builder设计模式和Factory设计模式有什么区别? 哪一个更有利,为什么? 如果我想测试和比较/对比这些模式,如何将我的发现表示为图形? #1楼 建筑商和抽象工厂 在某种程度上,Builder ...

最新文章

  1. 网站制作基本要素了解一下
  2. 批评“古风”歌词“狗屁不通”就是不尊重?我们又都成了“垃圾听众”
  3. 易语言逐条读access数据_易语言对ACCESS数据库基础(适合新手)
  4. K8s 集群节点在线率达到 99.9% 以上,扩容效率提升 50%,我们做了这 3 个深度改造
  5. jq之animate() toggle
  6. 关于获取多个屏幕分辨率以及进行一些设置
  7. OPC DA通讯 KEP6.4 DCOM 配置脚本
  8. 电路板的信号完整性问题及原因
  9. 一个悄然成为世界最流行的操作系统
  10. python中常见的三种选择结构_循序渐进学Python:三种选择语句
  11. IMPLEMENT_DYNCREATE(CFileView, CView)
  12. GPS坐标与UTM坐标的转换
  13. php网站背景颜色代码,html如何设置背景颜色?
  14. CPU的内部架构和工作原理(转)
  15. C++ 类型A支持强制转换类型B的写法
  16. 内网实现电视盒子访问PC
  17. 生信工作流框架搭建 | 02-nextflow 实战
  18. F005MyBatis学习笔记-MyBatis的多表关联查询
  19. python简单代码画皮卡丘-利用Python绘制萌萌哒的皮卡丘
  20. 软件著作权申请流程及注意事项,你知道多少?

热门文章

  1. Vision GUI programming products
  2. Dreamweaver 制作图片热点之后,点击热点部分会有个提示框,怎么去掉
  3. FreeBSD8下安装软件相关
  4. 随机取出若干条记录的SQL语句
  5. docker下安装mysql数据库
  6. (6)tcp-socket
  7. 多线程经典模型-生产者消费
  8. 【c++ primer读书笔记】【第6章】函数
  9. 2.SDK目录结构和adb工具及命令介绍
  10. .Net程序集强签名详解