О примерном определении
Я читал из книги о предварительном дефинировании, что,
Предварительное определение - это любое объявление внешних данных, которое не имеет спецификатора класса хранения и не имеет инициализатора. Предварительное определение становится полным определением, если конец единицы перевода достигнут, и определение не появилось с инициализатором для идентификатора
Пожалуйста, объясните, что означает вышеуказанное утверждение. Кроме того, разница между Декларацией и определением? Из-за этого я перепутался. :( И почему эта программа не дает ошибку:
#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;
}
Ответы
Ответ 1
Объявление переменной говорит: "в программе есть переменная со следующим именем и типом".
Определение переменной говорит: "Дорогой г-н Компилятор, выделите память для переменной со следующим именем и введите сейчас".
Таким образом, для одной и той же переменной может быть несколько объявлений, но должно быть только одно определение.
В C чистым объявлениям (которые не являются также определениями) предшествует ключевое слово extern
. Итак, поскольку у вас нет этого ключевого слова в первом примере, у вас есть два определения. На первый взгляд это кажется проблемой (и на самом деле является ошибкой в С++), но C имеет специальное правило "предварительного определения", которое допускает несколько определений для одной и той же переменной, пока все они совпадают, и не более одного имеет инициализатор. Компилятор C за кулисами объединяет все предварительные определения в единое определение.
Если вы попытались инициализировать оба определения, например:
int a = 1;
int a = 2;
Тогда у вас была бы ошибка.
Ваш второй вопрос более прост. В C вы просто не можете иметь исполняемые операторы вне тела функции. Это просто не разрешено. Подумайте об этом: когда вы ожидаете, что он запустится, если это разрешено?
Ответ 2
Первое работает, потому что оба определения a
являются предварительными, которые можно дублировать так часто, как вы сочтете нужным. В конце единицы перевода не было обнаружено неопределенного определения, поэтому то, что вы указали для атрибутов, сочетается с значениями по умолчанию, чтобы дать окончательное определение a
, поэтому оно будет иметь внешнюю связь, статическую продолжительность хранения, и быть инициализированным до 0.
Проблема со вторым не имеет ничего общего с предварительными определениями. Ваш printf("Hi");
должен находиться внутри функции для работы - это не декларация или определение (предварительное или иное); это просто не допускается.