О предварительном определении - PullRequest
33 голосов
/ 22 июня 2010

Я прочитал из книги о предварительном определении этого,

Предварительное определение - любое внешнее объявление данных, которое не имеет спецификатор класса хранения без инициализатора. Предварительное определение становится полным определением, если конец блока перевода достигнуто, и с инициализатором для Идентификатор

Пожалуйста, объясните, что означает приведенное выше утверждение. Кроме того, разница между декларацией и определением? Я запутался из-за этого. :( И почему эта программа не выдает ошибку:

#include <stdio.h>

int a;      //Tentative definition
int a;      //similarly this declaration too.
int main()  //not getting any error with this code why its so?
{
    printf("hi");
} 

Кроме того, что не так с этим кодом:

#include<stdio.h>
printf("Hi");
int main(void){
    return 0;
}

Ответы [ 2 ]

60 голосов
/ 22 июня 2010

Переменная объявление говорит: «в программе есть переменная со следующим именем и типом».

Переменная определение говорит: «Уважаемый мистер Компилятор, пожалуйста, выделите память для переменной со следующим именем и типом сейчас».

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

В C чистым объявлениям (которые также не являются определениями) предшествует ключевое слово extern. Итак, поскольку в первом примере у вас нет этого ключевого слова, у вас есть два определения. На первый взгляд, это может показаться проблемой (а на самом деле это ошибка в C ++), но в C есть специальное правило «предварительного определения», которое допускает несколько определений для одной и той же переменной, если они все совпадают и не превышают имеет инициализатор. За кулисами компилятор C объединяет все предварительные определения в одно определение.

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

int a = 1;
int a = 2;

Тогда у вас была бы ошибка.

Ваш второй вопрос более прост. В C вы просто не можете иметь исполняемые операторы вне тела функции. Это просто запрещено. Подумайте об этом: когда вы ожидаете, что он запустится, если это будет разрешено?

11 голосов
/ 22 июня 2010

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

Проблема со вторым не имеет ничего общего с предварительными определениями.Ваш printf("Hi"); должен быть внутри функции, чтобы работать - это не объявление или определение (предварительное или иное);это просто не разрешено там.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...