В чем разница между определением и декларацией?

718

Значение обоих ускользает от меня.

  • 87
    @Lasse: не правда. Определение и определяет, и объявляет ;-)
  • 13
    Честно говоря, у меня было много проблем с обучением, поэтому я не нашел названия очевидными. У меня не было проблем со значениями, только то, какие имена ассоциируются со значениями.
Показать ещё 10 комментариев
Теги:
declaration
definition
terminology
c++-faq

26 ответов

765
Лучший ответ

Объявление вводит идентификатор и описывает его тип, будь то тип, объект или функция. Объявление , что компилятор нуждается, чтобы принимать ссылки на этот идентификатор. Это объявления:

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

A определение фактически создает/реализует этот идентификатор. Это , что требуется компоновщику, чтобы связать ссылки на эти объекты. Это определения, соответствующие указанным выше объявлениям:

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

Определение может быть использовано в месте объявления.

Идентификатор может быть объявлен так часто, как вы хотите. Таким образом, в 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);

Однако он должен быть определен ровно один раз. Если вы забыли определить что-то, что было объявлено и где-то указано, то компоновщик не знает, на что ссылаться ссылки и жалуется на недостающие символы. Если вы определяете что-то более одного раза, то компоновщик не знает, какое из определений ссылается на ссылки и жалуется на дублированные символы.


Поскольку дискуссия о том, что представляет собой объявление класса, или определение класса в С++, продолжает появляться (в ответах и ​​комментариях к другим вопросам), здесь я вставляю цитату из стандарта С++.
В 3.1/2 С++ 03 говорит:

Объявление является определением, если оно [...] является объявлением имени класса [...].

3.1/3 дает несколько примеров. Среди них:

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

Подводя итог: стандарт С++ рассматривает struct x; как объявление и struct x {}; определение. (Другими словами, "форвардная декларация" является неправильным выражением, поскольку в С++ нет других форм объявлений классов.)

Благодаря litb (Johannes Schaub), который выкопал настоящую главу и стих в одном из своих ответов.

  • 1
    Является ли это многократным объявлением законным в соответствии со стандартом, или вашим компилятором, или как? Я не могу сделать это несколько раз в одной области.
  • 2
    @unknown: либо ваш компилятор не работает, либо вы неправильно скопировали код sbi. Например, 6.7.2 (2) в N1124: «Все объявления, которые ссылаются на один и тот же объект или функцию, должны иметь совместимый тип; в противном случае поведение не определено».
Показать ещё 27 комментариев
152

Из стандартного раздела С++ 3.1:

Объявление вводит имена в единицы перевода или имена редекларов, введенные предыдущими деклараций. Объявление определяет интерпретацию и атрибуты этих имен.

В следующем параграфе говорится (подчеркивание мое), что объявление является определением, если...

... он объявляет функцию без указания функций 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
}

... или является выражением typedef или using.

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

Теперь по большой причине важно понять разницу между объявлением и определением: Правило определения. Из раздела 3.2.1 стандарта С++:

Никакая единица перевода не должна содержать более одного определения любой переменной, функции, типа класса, типа перечисления или шаблона.

  • 0
    «объявляет статический член в определении класса» - это правда, даже если статический член инициализирован, верно? Можем ли мы сделать пример struct x {static int b = 3; }; ?
  • 0
    @RJFalconer Вы правы; инициализация не обязательно превращает объявление в определение (вопреки тому, что можно ожидать; конечно, я нахожу это удивительным). Ваша модификация примера на самом деле незаконна, если только b не объявлено как const См stackoverflow.com/a/3536513/1858225 и daniweb.com/software-development/cpp/threads/140739/... .
Показать ещё 2 комментария
107

Декларация: "Где-то существует foo".

Определение: "... и вот оно!"

  • 3
    Декларация предназначена для того, чтобы компилятор принял имя (чтобы сообщить компилятору, что имя допустимо, имя вводится с намерением, а не опечаткой). Определение - это то, где имя и его содержание связаны. Определение используется компоновщиком для связи ссылки на имя с содержанием имени.
43

В С++ имеются интересные краевые случаи (некоторые из них тоже в 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".

В С++ при использовании шаблонов есть еще один край.

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, то не создавайте экземпляр определения члена из основного шаблона, а используйте определение, найденное в другом месте". Чтобы сделать это определение, вы должны предоставить инициализатор

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

Декларация

В объявлениях сообщается компилятору, что элемент или имя программы существует. декларация вводит один или несколько имена в программу. Объявления могут встречаются более одного раза в программе. Поэтому классы, структуры, перечислены типы и другие определяемые пользователем типы могут быть объявлены для каждая единица компиляции.

Определение

Определения определяют, какой код или данные имя описывает. Имя должно быть объявленный до его использования.

  • 0
    Хм, разве вы не можете даже определить классы и перечисления в каждом модуле компиляции? По крайней мере, я помещаю определения классов в свои заголовки и включаю их во все. Er, class foo {}; является определение класса, не так ли?
  • 1
    Да. Тем не менее, "класс Foo;" это декларация. Он сообщает компилятору, что foo - это класс. "class foo {};" это определение. Он сообщает компилятору, что это за класс foo.
Показать ещё 5 комментариев
18

Из стандарта C99, 6.7 (5):

Объявление определяет интерпретацию и атрибуты набора идентификаторов. Определение идентификатора - это объявление для этого идентификатора, которое:

  • для объекта, заставляет хранилище зарезервировать для этого объекта;
  • для функции включает тело функции;
  • для константы перечисления или имени typedef, является (единственным) объявлением Идентификатор.

Из стандарта С++, 3.1 (2):

Объявление - это определение, если оно не объявляет функцию без указания тела функции, содержит спецификатор extern или спецификацию привязки, а также ни инициализатор, ни тело функции, он объявляет статический член данных в объявлении класса, это объявление имени класса, или это объявление typedef, служебная декларация или директива using.

Тогда есть несколько примеров.

Так интересно (или нет, но я немного удивлен этим), typedef int myint; - это определение в C99, но только объявление в С++.

  • 0
    @onebyone: Что касается typedef , разве это не значит, что его можно повторить в C ++, но не в C99?
  • 0
    Это то, что удивило меня, и в том, что касается одного переводчика, да, в этом есть разница. Но ясно, что определение типа может быть повторено в C99 в разных единицах перевода. C не имеет явного «правила одного определения», как C ++, поэтому правила, которые он имеет, просто позволяют это. C ++ решил изменить его на объявление, но также одно правило определения перечисляет, к каким вещам оно относится, и typedefs не является одним из них. Таким образом, повторы будут разрешены в C ++ под ODR, как это сформулировано, даже если определение типа является определением. Кажется излишне придирчивым.
Показать ещё 11 комментариев
13

Из 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; 

см. Answers.

  • 3
    Это тоже неправильно (хотя и гораздо ближе, чем другие): struct foo {}; это определение , а не декларация. Объявление foo было бы struct foo; , Исходя из этого, компилятор не знает, сколько места зарезервировать для объектов foo .
  • 0
    sbi, мой ответ отражает то, что вы говорите. в вашем примере вы определяете foo как пустую структуру. Я не понимаю, как наши примеры технически отличаются.
Показать ещё 7 комментариев
12

Обновление С++ 11

Поскольку я не вижу ответа, относящегося к С++ 11, здесь.

Объявление - это определение, если оно не объявляет /n:

  • opaque enum - enum X : int;
  • параметр шаблона - T в template<typename T> class MyArray;
  • объявление параметра - x и y в int add(int x, int y);
  • Объявление псевдонима - using IntVector = std::vector<int>;
  • Объявление static assert - static_assert(sizeof(int) == 4, "Yikes!")
  • объявление атрибута (определяется реализацией)
  • пустое объявление ;

Дополнительные предложения, унаследованные от С++ 03 в приведенном выше списке:

  • Объявление функции - добавьте int add(int x, int y);
  • спецификатор extern, содержащий объявление или спецификатор привязки - extern int a; или extern "C" { ... };
  • статический член данных в классе - x в class C { static int x; };
  • Объявление класса/структуры - 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
4

Декларация:

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 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;
  • 0
    int a; //declaration; a=10; //definition Это совершенно неправильно. Когда речь идет об объектах длительности автоматического хранения (объекты, объявленные внутри определения функции, которые не объявлены с другим спецификатором класса хранения, например extern), это всегда определения.
  • 0
    Основное отличие, которое нужно понять, заключается в том, что в декларации говорится, что «где-то существует вещь, имеющая эти черты (тип и т. Д.)», В то время как определение гласит: «Я объявляю вещь с этими чертами, и я также создаю ее здесь как Что ж." Поскольку вы не можете пересылать объявленные объекты продолжительности автоматического хранения, они всегда будут определениями.
Показать ещё 1 комментарий
4

определение означает, что фактическая функция написана и декларация означает простую функцию объявления например.

void  myfunction(); //this is simple declaration

и

void myfunction()
{
 some statement;    
}

это определение функции myfunction

  • 1
    А как насчет типов и объектов?
3

Общее правило:

  • Объявление сообщает компилятору, как интерпретировать переменные данные в памяти. Это необходимо для каждого доступа.

  • A определение резервирует память, чтобы сделать существующую переменную. Это должно произойти ровно один раз перед первым доступом.

  • 2
    Это относится только к объектам. А как насчет типов и функций?
2

Найти похожие ответы здесь: Технические вопросы для интервью в C

Объявление содержит имя программы; определение предоставляет уникальное описание объекта (например, типа, экземпляра и функции) внутри программы. Объявления могут быть повторены в заданной области, он вводит имя в заданной области.

Объявление - это определение, если

  • Декларация объявляет функцию без указания ее тела,
  • В декларации содержится спецификатор extern и нет элемента инициализации или функции,
  • Декларация - это объявление элемента данных статического класса без определения класса,
  • Декларация - это определение имени класса,

Определение - это объявление, если:

  • Определение определяет элемент данных статического класса,
  • Определение определяет неединичную функцию-член.
2

Не могли бы вы заявить в наиболее общих терминах, что объявление является идентификатором, в котором не распределено хранилище, и определение фактически распределяет память из объявленного идентификатора?

Одна интересная мысль - шаблон не может распределять память до тех пор, пока класс или функция не будут связаны с информацией о типе. Так является ли идентификатор шаблона декларацией или определением? Это должно быть объявление, так как не распределено хранилище, и вы просто "прототипируете" класс или функцию шаблона.

  • 1
    Ваше определение само по себе не является неправильным, но «определение хранилища» всегда кажется неловким, когда речь идет об определениях функций. Относительно шаблонов: этот template<class T> struct foo; это объявление шаблона, как и этот template<class T> void f(); , Определения шаблонов отражают определения классов / функций таким же образом. (Обратите внимание, что имя шаблона не является именем типа или функции . Это можно увидеть в одном месте, когда вы не можете передать шаблон в качестве параметра типа другого шаблона. Если вы хотите передавать шаблоны вместо типов, вам нужны параметры шаблона шаблона. )
  • 0
    Согласился, что «определение хранилища» неудобно, особенно в отношении определений функций. Объявление int foo () и определение int foo () {// некоторый код здесь ..}. Мне обычно нужно обернуть свой маленький мозг знакомыми мне понятиями - «хранилище» - это, по крайней мере, один из способов сохранить его как минимум для меня… :)
1

Согласно руководству библиотеки GNU C (http://www.gnu.org/software/libc/manual/html_node/Header-Files.html)

В C декларация просто предоставляет информацию о существовании функции или переменной и дает ее тип. Для объявления функции может быть предоставлена ​​информация о типах ее аргументов. Цель деклараций - дать возможность компилятору правильно обрабатывать ссылки на объявленные переменные и функции. Определение, с другой стороны, фактически распределяет память для переменной или говорит, что делает функция.

1

Чтобы понять существительные, сначала сосредоточьтесь на глаголах.

объявить - официально объявить; провозглашают

определить - показать или описать (кто-то или что-то) ясно и полностью

Итак, когда вы что-то объявляете, вы просто рассказываете, что это такое.

// declaration
int sum(int, int);

Эта строка объявляет функцию C, называемую sum, которая принимает два аргумента типа int и возвращает int. Однако вы еще не можете его использовать.

Когда вы указываете, как это работает, это определение.

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

Чтобы понять разницу между объявлением и определением, нам нужно увидеть код сборки:

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)

Объявление не имеет эквивалентной инструкции, потому что это не что-то, что нужно выполнить.

Кроме того, объявление объявляет компилятору область действия переменной.

Мы можем сказать, что объявление - это информация, используемая компилятором для установления правильного использования переменной и того, как долго некоторая память принадлежит определенной переменной.

1

Это будет звучать действительно дрянным, но это лучший способ, которым я мог держать слова прямо в моей голове:

Декларация: изображение Томаса Джефферсона, выступающего с речью... "Я НАСТОЯЩИМ ЗАЯВЛЯЮ, ЧТО ЭТО ЭТО ПРЕДУПРЕЖДЕН В ЭТОМ ИСТОЧНИКЕ КОДА!!!"

Определение: изобразите словарь, вы смотрите Foo и на что он на самом деле означает.

1

Декларация означает указание имени и типа переменной (в случае объявления переменной) например:

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

В приведенных выше случаях мы определяем и объявляем переменную я и функцию max()

  • 0
    фактическое среднее значение определения, если присвоить значение / тело переменной / функции, тогда как объявление означает предоставление имени, типа переменной / функции
  • 0
    Вы можете определить что-то без присвоения ему значения.
Показать ещё 4 комментария
0

Как этапы компиляции

(1) для каждого процессора → (2) переводчик → (3) ассемблер → (4) компоновщик

перед тем, как перейти на (2) этап (переводчик/компилятор), заявления декларации в нашем коде, которые пытаются рассказать (2) о том, что эти вещи мы будем использовать в будущем, и вы можете найти определение позже, а это означает:

переводчик убедитесь, что: что есть? означает объявление

и (4) этап (линкер) нуждается в определении, чтобы связать вещи

Linker убедитесь, что: где и что? означает определение

0

Переменная объявлена ​​, когда компилятор информирован о существовании переменной (и это ее тип); он не выделяет хранилище для переменной в этой точке.

Переменная определена, когда компилятор выделяет хранилище для переменной.

0

В объявлении представлено имя символа компилятору. Определение - это объявление, которое выделяет пространство для символа.

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

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

Всякий раз, когда мы записываем функцию после основной функции, компилятор будет через ошибку, поскольку он не имеет представления о функции во время вызова функции. Если мы предоставим прототип объявления функции, то мы, компилятор, не будем искать определения.

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;

Переменная декларация Vs Определение Параметры дифференциации

а. Космическое резервирование:

Всякий раз, когда мы объявляем переменную, пространство не будет зарезервировано для переменной. Всякий раз, когда мы объявляем переменную, компилятор не будет искать другие данные, такие как определение переменной.

Декларация - удобный способ написания кода, в котором фактическая память не выделена.

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

В вышеуказанной декларации память не выделяется. Всякий раз, когда мы определяем переменную, тогда для переменной будет выделена память.

struct book b1;

В. Что он делает?

  • Декларация идентифицирует тип данных идентификатора.
  • Определение переменной присваивает ей значение.
0

Моим любимым примером является "int Num = 5", здесь ваша переменная равна 1. определяется как int 2. объявляется как Num и 3. создается экземпляр со значением пять. Мы

  • Определите тип объекта, который может быть встроен, или класс или структура.
  • Объявить имя объекта, поэтому было объявлено что-либо с именем, которое включает переменные, Funtions и т.д.

Класс или структура позволяет вам изменить способ определения объектов, когда он будет использоваться позднее. Например

  • Можно объявить гетерогенную переменную или массив, которые конкретно не определены.
  • Используя смещение в С++, вы можете определить объект, который не имеет объявленного имени.

Когда мы изучаем программирование, эти два термина часто путают, потому что мы часто делаем оба одновременно.

  • 0
    Я не понимаю, почему так много людей проголосовали за ответ sbi. Я действительно одобрил ответ bjhend, который был довольно хорошим, сжатым, точным и гораздо более своевременным, чем мой. Мне было грустно видеть, что я был первым человеком, который сделал это за 4 года.
0

Концепция декларации и определения будет представлять собой ловушку, если вы используете класс внешнего хранилища, потому что ваше определение будет находиться в каком-то другом месте, и вы объявляете переменную в вашем локальном файле кода (странице). Одна разница между C и С++ заключается в том, что в C вы декларации выполняются обычно в начале функции или кодовой страницы. В С++ это не так. Вы можете объявить в выбранном вами месте.

  • 1
    Это путает декларацию с определением и совершенно неверно.
0

Разница между объявлением и определением с помощью функций: Оператор prototype для функции объявляет его, то есть сообщает компилятору о функции - ее имени, типе возвращаемого номера, числе и типе его параметров. Заголовок функции, за которым следует тело функции, определяет функцию - дающую подробную информацию о шагах для выполнения функции.

Исх.

код:

//Declare
int foo(int);

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

С уважением к переменным: Для автоматических и регистровых переменных нет разницы между определением и декларацией. Процесс объявления автоматической или регистровой переменной определяет имя переменной и выделяет соответствующую память.

Однако для внешних переменных: Поскольку память для переменной должна быть назначена только один раз, чтобы гарантировать, что доступ к переменной всегда относится к одной и той же ячейке. все переменные должны быть определены один раз и только один раз.

Если внешняя переменная должна использоваться в файле, отличном от того, в котором он определен, необходим механизм для "подключения" такого использования с выделенной для него однозначно определенной внешней переменной. Этот процесс соединения ссылок одной и той же внешней переменной в разных файлах называется разрешением ссылок.

Он может быть определен и объявлен с помощью оператора объявления вне любой функции без спецификатора класса хранения. Такое объявление выделяет память для переменной. Оператор объявления также может использоваться для простого объявления имени переменной с помощью спецификатора класса extern storage в начале объявления. Такое объявление указывает, что переменная определена в другом месте, то есть память для этой переменной выделяется в другом файле. Таким образом, доступ к внешней переменной в файле, отличном от того, в котором он определен, возможен, если он объявлен с ключевым словом extern; не выделяется новая память. Такое объявление сообщает компилятору, что переменная определена в другом месте, а код скомпилирован с внешней переменной, оставленной неразрешенной. Ссылка на внешнюю переменную разрешена во время процесса компоновки.

Исх.

код

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

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

Эти объявления сообщают компилятору, что переменные stack [] и stkptr определены в другом месте, обычно в каком-то другом файле. Если ключевое слово extern было опущено, переменные будут считаться новыми, и для них будет выделена память. Помните, что доступ к одной и той же внешней переменной, определенной в другом файле, возможен только в том случае, если в объявлении используется ключевое слово extern.

0

В объявлении вводится имя в программу; определение предоставляет уникальное описание объекта (например, тип, экземпляр и функция). Объявления могут быть повторены в заданной области, он вводит имя в заданной области. Должно быть точно одно определение каждого объекта, функции или класса, используемых в программе на С++. Декларация является определением, если:

* 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.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню