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

Глобальные переменные в файле заголовка

У меня есть 2 модуля (.c файлы) и один .h заголовочный файл:

file1.c:

#include <stdio.h>
#include "global.h"

int main()
{
    i = 100;
    printf("%d\n",i);
    foo();
    return 0;
}

file2.c

#include <stdio.h>
#include "global.h"

void foo()
{
    i = 10;
    printf("%d\n",i);
}

global.h

int i;
extern void foo()

Когда я делаю gcc file1.c file2.c, все работает отлично, и я получаю ожидаемый результат. Теперь, когда я инициализирую переменную "i" в файле заголовка, чтобы сказать "0" и снова скомпилировать, я получаю ошибку компоновщика:

/tmp/cc0oj7yA.o:(.bss+0x0): multiple definition of `i'
/tmp/cckd7TTI.o:(.bss+0x0): first defined here

Если я просто компилирую файл file1.c(удаление вызова в foo()) с инициализацией в файле заголовка, то есть gcc file1.c, все работает нормально. Что происходит?

4b9b3361

Ответ 1

Существует 3 сценария:

  • с 2 .c файлами и int i; в заголовке.
  • С 2 .c файлами и int i=100; в заголовке (или любом другом значении; это не имеет значения).
  • С 1 .c файлом и int i=100; в заголовке.

В каждом сценарии представьте содержимое файла заголовка, вставленного в файл .c, и этот файл .c, скомпилированный в файл .o, а затем связанный вместе.

Затем происходит следующее:

  • отлично работает из-за уже упомянутых "предварительных определений": каждый файл .o содержит один из них, поэтому компоновщик говорит "ok".

  • не работает, потому что оба файла .o содержат определение со значением, которое сталкивается (даже если они имеют одинаковое значение) - может быть только один с любым заданным именем во всех .o файлы, которые связаны в данный момент времени.

  • работает, конечно, потому что у вас есть только один .o файл и поэтому нет возможности для столкновения.

ИМХО чистая вещь будет

  • поставить либо extern int i;, либо просто int i; в заголовочный файл,
  • а затем поставить "реальное" определение я (а именно, int i = 100;) в file1.c. В этом случае эта инициализация используется в начале программы, и соответствующая строка в main() может быть опущена. (Кроме того, я надеюсь, что именование является лишь примером, и не называйте глобальные переменные как i в реальных программах.)

Ответ 2

Не инициализировать переменные в заголовках. Поместите объявление в заголовок и инициализацию в одном из файлов c.

В заголовке:

extern int i;

В файле2.c:

int i=1;

Ответ 3

Вы не должны определять глобальные переменные в файлах заголовков. Вы можете объявить их как extern в файле заголовка и определить их в исходном файле .c.

(Примечание: В C, int i; - предварительное определение, оно выделяет память для переменной (= это определение), если для этой переменной не найдено другого определения.)

Ответ 4

Dont определить varibale в файле заголовка, сделать объявление в файле заголовка (хорошая практика).. в вашем случае он работает, потому что несколько слабых символов.. Читайте о слабом и сильном символе.... link: http://csapp.cs.cmu.edu/public/ch7-preview.pdf

Этот тип кода создает проблему при портировании.