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

О примерном определении

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

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

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

#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;
}
4b9b3361

Ответ 1

Объявление переменной говорит: "в программе есть переменная со следующим именем и типом".

Определение переменной говорит: "Дорогой г-н Компилятор, выделите память для переменной со следующим именем и введите сейчас".

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

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

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

int a = 1;
int a = 2;

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

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

Ответ 2

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

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