提问



两个人的意思都没有。

最佳参考


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


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)在他的一个答案中挖出了实际章节和诗句。

其它参考1


从C ++标准3.1节:



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



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


...它声明了一个函数而没有指定函数的主体


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节:



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


其它参考2


宣言:某处,有一个foo。


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

其它参考3


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 
struct X { 
  static int member; // declaration
};

template
int X::member; // definition

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


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


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

其它参考4


声明



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



定义



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


其它参考5


从C99标准来看,6.7(5):


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



  • 表示对象,导致为该对象保留存储空间;

  • 用于函数,包括函数体;

  • 表示枚举常量或typedef名称,是(唯一)声明的
    标识符。



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


声明是定义除非它声明一个函数而没有指定函数体,它包含extern说明符或者链接规范,既不是初始化器也不是函数体,它声明了一个静态数据类声明中的成员,它是类名声明,或者是typedef声明,using声明或using-directive。


然后有一些例子。


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

其它参考6


来自wiki.answers.com:


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


例如,以下是所有声明:


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; 


见答案。[76]

其它参考7


C ++ 11更新



因为我没有看到与C ++ 11相关的答案。


声明是定义,除非它声明了一个/n:



  • opaque enum - enum X : int;

  • 模板参数 - template class MyArray;
  • 中的 T
  • 参数声明 - int add(int x, int y);
  • 中的 x 和 y
  • 别名声明 - using IntVector = std::vector;

  • 静态断言声明 - static_assert(sizeof(int) == 4, "Yikes!")

  • 属性声明(实现定义)

  • 空声明;



以上列表从C ++ 03继承的附加子句:



  • 函数声明 - int add(int x, int y);
  • 中的 add
  • 包含声明或链接说明符的extern说明符 - extern int a;extern "C" { ... };

  • 类中的静态数据成员 - class C { static int x; };
  • 中的 x
  • class/struct declaration - struct Point;

  • typedef declaration - typedef int Int;

  • 使用声明 - using std::cout;

  • using directive - 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;     // declares IntVector as an alias to std::vector
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 C;             // declares template class C
;                                       // declares nothing

其它参考8


定义意味着写的实际功能&声明意味着简单的声明功能
例如


void  myfunction(); //this is simple declaration





void myfunction()
{
 some statement;    
}


这是函数myfunction的定义

其它参考9


声明:


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 
void print(int a)
{
     printf("%d",a);
}
main()
{
    print(5);
}


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


计划2


 #include 
 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;

其它参考10


经验法则:



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

  • 定义保留内存以使变量存在。这必须在首次访问之前发生一次。


其它参考11


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


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

其它参考12


在这里找到类似的答案:C [77]中的技术面试问题


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


声明是一个定义,除非



  • 声明声明了一个函数,但没有指定它的主体,

  • 声明包含一个extern说明符,没有初始化器或函数体,

  • 声明是没有类定义的静态类数据成员的声明,

  • 声明是一个类名定义,



定义是声明,除非:



  • 定义定义静态类数据成员

  • 定义定义非内联成员函数。


其它参考13


声明意味着给变量赋予名称和类型(在变量声明的情况下)
例如:


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


在上面的例子中,我们定义并声明变量i和函数max()

其它参考14


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


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


定义:图片字典,你正在查找Foo及其实际含义。

其它参考15


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


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 
def=5;                     |  movb    $0x5,-0x45(%rbp)


宣言没有等同的指令,因为它不是要执行的东西。


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


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

其它参考16


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


声明 -
正式宣布;宣布


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


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


// declaration
int sum(int, int);


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


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


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

其它参考17


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



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


其它参考18


声明在程序中引入了一个名称;定义提供实体的唯一描述(例如,类型,实例和功能)。声明可以在给定范围内重复,它在给定范围内引入名称。对于C ++程序中使用的每个对象,函数或类,必须只有一个定义。
声明是一个定义,除非:


* it declares a function without specifying its body,
* it contains an extern specifier and no initializer or function body,
* it is the declaration of a static class data member without a class definition,
* it is a class name definition,
* it is a typedef declaration.


定义是声明,除非:


* it defines a static class data member,
* it defines a non-inline member function.

其它参考19


声明和定义函数之间的区别:
函数的原型语句声明它,即告诉编译器函数 - 它的名称,返回类型,以及它的参数的数量和类型。
函数头后跟函数体,定义函数 - 给出执行函数操作的步骤的详细信息。


防爆。


码:


//Declare
int foo(int);

//Define
int foo(int){
...
}


关于变量:
对于自动和寄存器变量,定义和声明之间没有区别。
声明自动或寄存器变量的过程定义变量名称并分配适当的内存。


但是,对于外部变量:
因为变量的内存只能分配一次,所以要确保对变量的访问始终引用同一个单元格。
所有变量必须只定义一次。


如果要在除定义它之外的文件中使用外部变量,则需要一种机制来将这种用途连接到为其分配的唯一定义的外部变量单元。在不同文件中连接相同外部变量的引用的过程称为解析引用。


它可以在任何函数外部使用声明语句定义和声明,不包含存储类说明符。这样的声明为变量分配内存。声明语句也可用于在声明开头简单地声明带有extern存储类说明符的变量名。这样的声明指定变量在别处定义,即该变量的内存在另一个文件中分配。因此,如果使用关键字extern声明外部变量,则可以访问除定义外部变量之外的文件中的外部变量。没有分配新的内存。这样的声明告诉编译器变量是在别处定义的,并且代码是在外部变量未解析的情况下编译的。在链接过程中解析对外部变量的引用。


防爆。





//file1.c
extern char stack[10];
extern int stkptr;
....

//file2.c
char stack[10];
int stkptr;
....


这些声明告诉编译器变量stack [[]]和stkptr在其他地方定义,通常在其他文件中。如果省略关键字extern,则变量将被视为新变量,并将为它们分配内存。请记住,只有在声明中使用关键字extern时,才可以访问另一个文件中定义的相同外部变量。

其它参考20


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

其它参考21


我最喜欢的例子是int Num=5,这里你的变量是1.定义为int 2.声明为Num和3.实例化为值为5。我们



  • 定义对象的类型,可以是内置类或类或结构。

  • 声明对象的名称,因此声明了包含变量,功能等的任何名称。



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



  • 可以声明一个未明确定义的异构变量或数组。

  • 在C ++中使用偏移量,您可以定义一个没有声明名称的对象。



当我们亚博2018平台编程时,这两个术语经常被混淆,因为我们经常同时做这两个术语。

其它参考22


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


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

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

其它参考23


当编译器被告知变量存在时(这是它的类型),变量是声明;它不会在该点为变量分配存储空间。


当编译器为变量分配存储时,变量已定义

其它参考24


每当我们在main函数之后编写函数时,编译器都会通过错误,因为它在调用函数时对函数没有任何了解。如果我们提供函数的原型声明,那么编译器将不会查找定义。


int sum(int,int);

main()
{
    int res = sum(10,20);
}
int sum(int n1,int n2)
{
    return(n1+n2);
}


在上面的例子中,第一行被称为函数声明。


int sum(int,int);


声明变量


每当我们编写声明语句时,就不会为变量分配内存。变量声明将随机指定内存位置。


int ivar;
float fvar;


变量声明与定义微分参数


:一种。空间预订:


每当我们声明一个变量时,就不会为变量保留空格。
每当我们声明一个变量时,编译器就不会寻找其他细节,例如变量的定义。


声明是编写未分配实际内存的代码的便捷方式。


struct book  {
    int pages;
    float price;
    char *bname;
};


在上面的声明中没有分配内存。每当我们定义一个变量时,就会为变量分配内存。


struct book b1;


B中。它做了什么?



  1. 声明将标识标识符的数据类型。

  2. 变量的定义将为其赋值。