意义都躲开我。

有帮助吗?

解决方案

声明 引入标识符并描述其类型,无论是类型,对象还是函数。声明是 编译器需要 来接受对该标识符的引用。这些是声明:

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 {}; 定义。 (换句话说, <!> quot;前向声明<!>“用词不当 ,因为C ++中没有其他形式的类声明。)

感谢 litb(Johannes Schaub)挖出他的一个实际章节和经文答案。

其他提示

来自C ++标准3.1节:

  

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

下一段陈述(强调我的)声明是一个定义,除非......

...它声明了一个函数而没有指定函数<!>#8217; s body:

void sqrt(double);  // declares sqrt

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

struct X
{
    int a;         // defines a
    static 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节开始:

  

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

声明:<!>“;某处,有一个foo。<!>”;

定义:<!>“; ......这里是!<!>”

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; // definition

template<>
int X<bool>::member; // declaration!

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

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

<强>声明

  

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

<强>定义

  

定义指定代码或数据   这个名字描述。名字必须是   在可以使用之前声明。

从C99标准,6.7(5):

宣言规定的解释和属性的一的标识符。一个 定义 一个标识符的声明,标识:

  • 为对象,导致储存以保留,对象;
  • 用一个功能,包括功能的身体;
  • 枚举不变或typedef的名字,是(仅)的声明 标识符。

从C++标准,3.1(2):

一个宣言是一个 定义 除非宣布一个功能,而不指定功能的身体,它包含的外部说明符或有联系的规范和既不是一个初始化,也不是一个功能的身体,因此宣布一个静态数据成员在类声明,这是一个类名称的宣言,或者它是一个typedef宣言》,使用声明,或一种使用指令。

然后有一些例子。

这样有趣的是(或不是,但我略感到惊讶), typedef int myint; 是一个定义在C99,但只有《宣言》在C++。

从wiki.answers.com:

术语的声明装置(C)你是说的编译器种类、大小和在情况下的功能宣言》、类型和尺寸参数的任何变,或用户定义的类型或功能在您的节目。 没有 空间保留在存储器的任何可变的情况下宣言》。然而compiler知道有多少空间来的储备在情况变这种类型的创建。

例如,以下是所有声明:

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

定义,另一方面意味着增加所有的东西,《宣言》,空间也保留在记忆。你可以说"定义=宣言》+的空间保留"举例如下定义:

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

看看 答案.

C++11更新

因为我没有看到一个答案相关的C++11这里有一个。

一个宣言是一个 定义 除非它声明a/n:

  • 不透明的enum enum X : int;
  • 模板参数 Ttemplate<typename T> class MyArray;
  • 参数宣言-- xyint 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 "C" { ... };
  • 静态数据成员在一类 xclass C { static int x; };
  • 类/struct宣言》, struct Point;
  • typedef宣言》, typedef int Int;
  • 使用的宣言》, using std::cout;
  • 使用指令中- 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 X
    int x;                              // defines non-static data member x
    static int y;                       // DECLARES static data member y
    X(): 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

定义是指实际写入的函数<!> amp;声明意味着简单的声明功能 例如

void  myfunction(); //this is simple declaration

void myfunction()
{
 some statement;    
}

这是函数myfunction的定义

经验法则:

  • 一个 宣言 告诉编译器如何解释的变量的数据存储器中。这是需要每一个访问。

  • 一个 定义 保留记忆,使可变现有的。这发生了一次前第一次访问。

声明:

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);
}

在此,声明并定义了print函数。因为函数调用是在定义之后发生的。现在看下一个程序。

计划2

 #include <stdio.h>
 void print(int a); // In this case this is essential
 main()
 {
    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;

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

声明 - 正式宣布;宣布

定义 - 明确而完整地展示或描述(某人或某事)

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

// declaration
int sum(int, int);

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

当你提供它的实际工作方式时,就是它的定义。

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

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

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        # 0x400a20
                        movsd   %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        # 0x400a20
               movsd   %xmm0,-0x8(%rbp)

你可以看到没有任何改变。

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

看到:

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

声明没有等效指令,因为它不是要执行的东西。

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

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

难道你不能用最一般的术语说明声明是一个标识符,其中没有分配存储空间,定义实际上是从声明的标识符中分配存储空间的?

一个有趣的想法 - 在类或函数与类型信息链接之前,模板无法分配存储。那么模板标识符是声明还是定义?它应该是一个声明,因为没有分配存储空间,并且您只是简单地“模板化”模板类或函数。

找到类似的答案在这里: 技术的采访的问题在C.

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

一个宣言是一个定义,除非:

  • 《宣言》宣布一个功能,而未指定其主体,
  • 《宣言》包含一个外部说明符和没有初始化或功能的身体,
  • 《宣言》是《宣言》的一个静态的类数据的成员没有一个类的定义,
  • 《宣言》是一类名称的定义,

一个定义是一个宣言,除非:

  • 定义,定义了一个静态的类数据的成员,
  • 定义,定义了一个非联件的功能。

这听起来真的很俗气,但这是我能够将这些条款保持在我脑海中的最佳方式:

宣言:图片托马斯杰斐逊发表演讲...... <!>“我特此声明,这个源代码存在于此源代码中!!! <!>

定义:描绘一本字典,你正在查找Foo及其实际含义。

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

int f(int x); // function declaration (I know f exists)

int f(int x) { return 2*x; } // declaration and definition

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

  

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

声明意味着为变量提供名称和类型(在变量声明的情况下),例如:

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()

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

我最喜欢的例子是"int Num=5"在这里,你的变量是1。定义为int2.宣布为Num和3。实例有价值的五个。我们

  • 定义类型的对象,这可能是内在的或一类或结构中。
  • 声明对象的名称,所以任何与一名已宣布其中包括变量、功能,等等。

一类或结构允许你改变对象如何将定义时,它是以后使用。例如

  • 一个可以宣布一个异类变量或阵列是没有具体定义。
  • 使用一个偏C++你可以限定对象,它没有宣布的名字。

当我们学会编程这两个方面往往是困惑,因为我们往往在同一时间。

可执行代的阶段:

  

(1)预处理器 - <!> gt; (2)翻译/编译器 - <!> gt; (3)链接器

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

  

翻译确保:什么是什么?表示声明

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

  

链接器确保:在哪里?表示定义

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top