Внешняя переменная с разными типами в C - PullRequest
2 голосов
/ 26 января 2020

Я тестировал области и видимость, когда сталкивался с этой ситуацией. Я не могу найти объяснение:

У меня есть два. c файла:

F1 . c

#include <stdio.h>

void Modify();

int i;
int j;

int main()
{
  i=1;

  printf("i (main 1) = %d\n", i);

  Modify();

  printf("i (main 2) = %d\n", i);

  return 0;
}

и F2. c

#include <stdio.h>

extern char i [10];
extern int j;

void Modify()
{
  j=0;
  i[0]='a';
  i[1]= 'b';
  i[4]= 'e';

  printf("i (Modify) = %c\n", i[0]);
  printf("j (Modify) = %d\n", j);
}

Когда я компилирую и связываю их для создания исполняемого файла, который я запускаю , вот результат:

i (основной 1) = 1

i (Изменить) = a

j (Изменить) = 0

i (основной 2) = 25185

Что происходит? Меняет ли я типы? Дает ли массив с размером пересилить объявление i в F1. c?

Спасибо!

1 Ответ

5 голосов
/ 26 января 2020

Это противоречит правилам C. Внешние глобалы должны иметь согласованные декларации. (Вот почему мы используем заголовки для обеспечения согласованности.) Вы дали разрешение своему набору инструментов на создание беспорядка.

Как говорится, в вашем случае происходит просто наложение объектов (возможно, выделено достаточно памяти для int и char[10], как если бы там было * 1005. * Если выделено только 4 байта (только для int, а не для массива), то i[4] access перезапишет что-то или, что менее вероятно, вызовет ошибку.).

25185 равно 0x6261, что в предположении, что архитектура с прямым порядком байтов соответствует {0x61, 0x62, 0x00, 0x00}, т.е. ;, {'a', 'b', 0, 0 }. 'e' не входит в это число, потому что int вашей архитектуры имеют размер 4 байта, а 'e' был помещен в 5-й байт.

Опять вы находитесь в сфере UB , поэтому ничего из этого не гарантировано.

...