Подтвердить что ты не робот

Декларация или определение в C

От Внешние переменные Wiki:

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

Я не смог полностью понять смысл этого утверждения относительно C. Например, подразумевает ли это, что:

int i;

не обязательно является объявлением (как я предполагал до сих пор), но может также быть определением (по определению определения и декларации на той же веб-странице, каламбур не предназначен)?

Вкратце, это утверждение выше: а. просто объявление или б. Объявление + определение?

Ссылка: Объявление и определение переменных

Резюме полученных ответов:

                         Declaration    Definition    Tentative Definition   Initialized 
int i;   (inside a block)    Yes           Yes                No                No
int i=5; (inside a block)    Yes           Yes                No               Yes(to 5)
int i;   (otherwise)         Yes            No               Yes               Yes(to 0)
extern int i;                Yes            No                No                No


All definitions are declarations but not vice-versa.
4b9b3361

Ответ 1

В стандарте C говорится, что

Определение идентификатора - это объявление для этого идентификатора, которое: для объекта заставляет зарезервировать хранилище для этого объекта (...)

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

int i;

не является объявлением. Это декларация, которая также является определением. Или это определение, следовательно, декларация.

Ответ 2

Предполагая, что в области файлов это "предварительное определение". Из 6.9.2/2 "Определение внешних объектов":

Объявление идентификатора для объекта, имеющего область действия без инициализатора, и без спецификатора класса хранения или со спецификатором класса хранения static, представляет собой предварительное определение. Если единица перевода содержит одно или несколько предварительных определений для идентификатор, а единица перевода не содержит внешнего определения для этого идентификатора, то поведение точно такое же, как если бы единица перевода содержала объявление области видимости файла идентификатор с составным типом на конце блока перевода с инициализатором равным 0.

Это означает, что в блоке трансляции было бы также иметь следующее:

int i = 42;

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

Если декларация находится в области блоков, стандарт говорит следующее (6.2.2/2 "Связи идентификаторов" ):

Каждое объявление идентификатора с никакая ссылка не обозначает уникальную сущность.

...

(пункт 6) идентификаторы не имеют связи:... a идентификатор области блока для объекта объявлен без класса хранения спецификатор extern.

Таким образом, в области блоков декларация также является определением.

Ответ 3

В контексте переменных:

  • Объявление переменной - это инструкция, которая описывает, как выглядит эта переменная. Итак:

    extern int x;
    

    в глобальной области переводится на: "где-то в коде есть переменная с именем x, которая имеет тип int и внешнюю связь. Декларация необходима, прежде чем вы когда-нибудь обратитесь к x. (То же самое относится к объявления функций.)

  • Определение - это оператор, который создает экземпляр этой переменной. Итак:

    int x;
    

    в глобальной области видимости создает единственную переменную типа int с внешней связью. Поэтому, если вы поместили эту строку в заголовок, каждая единица перевода, включая этот заголовок, попытается создать свою собственную копию x, что нежелательно - поэтому у нас есть только объявления в файлах заголовков. То же самое касается функций: если вы предоставляете тело функции, это определение.

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

Ответ 4

Из спецификации C99:

Объявление идентификатора для объекта, имеющего область действия без инициализатора, и    без спецификатора класса хранения или со спецификатором класса хранения static, представляет собой       предварительное определение. Если единица перевода содержит одно или несколько предварительных определений для          идентификатор, а единица перевода не содержит внешнего определения для этого идентификатора, то               поведение точно такое же, как если бы единица перевода содержала объявление области видимости файла                идентификатор с составным типом на конце блока перевода с инициализатором                 равным 0.

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

Ответ 5

Поскольку C использует термины:

"Определение" создает что-то (которое занимает какую-то память). Он также описывает что-то. Это означает, что "определение" также является "объявлением".

"Декларация" просто что-то описывает. Идея заключается в том, что компилятор должен знать, как создать код, который использует вещь, определенную в другом месте. Позже компоновщик затем связывает использование с чем-то.

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