Переобучение глобальной переменной vs локальной переменной

Когда я скомпилирую код ниже

#include<stdio.h>

int main()
{
  int a;
  int a = 10;
  printf("a is %d \n",a);
  return 0;
}

Я получаю сообщение об ошибке:

test3.c: In function ‘main’:
test3.c:6:5: error: redeclaration of ‘a’ with no linkage
test3.c:5:5: note: previous declaration of ‘a’ was here

Но если я делаю переменную global, тогда она отлично работает.

#include<stdio.h>

int a;
int a = 10;
int main()
{
  printf("a is %d \n",a);
  return 0;
}

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

Ответ 1

В C оператор int a;, когда он сделан в области файла, является декларацией и предварительным определением. Вы можете иметь столько предварительных определений, сколько хотите, если они все соответствуют друг другу.

Если определение (с инициализатором) появляется до конца блока перевода, переменная будет инициализирована этим значением. Наличие нескольких значений инициализации - ошибка компилятора.

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

Вышеприведенное не применяется к локальным переменным. Здесь декларация также служит определением, и наличие нескольких ошибок приводит к ошибке.

Ответ 2

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

Локальная переменная

В C несколько локальных переменных не "сливаются" в один.

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

 #include<stdio.h>

 int main()
 {
  int a;
  int a = 10;
  printf("a is %d \n",a);  
  return 0;
 }

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

Глобальная переменная

В C несколько глобальных переменных "сливаются" в один. Таким образом, у вас действительно есть только одна глобальная переменная, объявленная несколько раз. Это происходит в то время, когда extern не был нужен (или, возможно, не существовал - не совсем уверен) в C.

Другими словами, все глобальные переменные с тем же именем будут преобразованы в одну переменную, поэтому ваш

#include<stdio.h>

int a;
int a = 10;
int main()
{
printf("a is %d \n",a);
return 0;
}

будет ссылаться на тот же самый объем памяти.

Ответ 3

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

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

если вы должны были объявить

int a = 5 int a = 10

в глобальной области (как в сегменте данных) конфликт будет иметь место, как ожидалось.