Многократное переопределение глобальной переменной as400 ILE C

У меня есть проект ILE C на as400, который при линковке выдает мне либо ошибку многократного переопределения глобальных переменных, либо неопределенные ссылки, если я ставлю глобальную переменную extern.

Вот код в самом простом виде:

основной:

#include "Header1"

int main(int argc, char** argv){
    int x = Foo();
    return 0;
}

Заголовок1

#ifndef HEADER1
#define HEADER1

struct MyStruct{
    int x;
};

struct MyStruct g_myStruct; /* My global struct variable. */

int Foo(void);

#endif

Реализация Заголовка1

#include "Header1"
#include "Header2"

int Foo(void){
    g_myStruct.x = 432;
    return Bar();
}

Заголовок2

#ifndef HEADER2
#define HEADER2

int Bar(void);

#endif

Реализация Заголовка2

#include "Header2"
#include "Header1"

int Bar(void){
    return g_myStruct.x;
}

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

Multiple strong definitions  . . . . . . . . . :   2
    Symbol    Type      Library     Object      Bound       Identifier
              *MODULE   MYLIB       1          *YES        g_myStruct
              *MODULE   MYLIB       I2          *YES        g_myStruct 

С ключевым словом extern перед объявлением моей глобальной структуры я получаю эту ошибку:

Unresolved references  . . . . . . . . . . . . :   2
    Symbol    Type      Library     Object      Bound       Identifier
              *MODULE   MYLIB       I1          *YES        g_myStruct
              *MODULE   MYLIB       I2          *YES        g_myStruct 

person aganm    schedule 10.09.2016    source источник
comment
Почему ваши заголовки не заканчиваются на .h?   -  person David Ranieri    schedule 10.09.2016
comment
Вы также забыли точку с запятой в реализации Header1: g_myStruct.x = 432, но исправив это, он должен скомпилироваться, можете ли вы показать ошибку?   -  person David Ranieri    schedule 10.09.2016
comment
@AlterMann В файловой системе as400 QSYS нет .h.   -  person aganm    schedule 10.09.2016
comment
@AlterMann Это просто опечатка. Все это компилируется, но не линкуется. Я добавил конкретные сообщения об ошибках.   -  person aganm    schedule 10.09.2016


Ответы (2)


Вы включаете файл header1.h в несколько разных исходных файлов.

Это приводит к нескольким различным экземплярам g_myStruct, таким образом, многократному переопределению.

Объявите эту переменную extern в файле header1.h и создайте ее экземпляр в одном из исходных файлов.


Например:

Файл header1.h:

extern struct MyStruct g_myStruct; /* My global struct variable. */

Файл header1.c:

struct MyStruct g_myStruct; /* My global struct variable. */
person barak manos    schedule 10.09.2016

Глобальные переменные работают почти так же, как и глобальные функции.


В заголовочном файле вы помещаете объявление. Для функций это выглядит так:

int Foo(void);  // or 'extern int Foo(void);'

Для переменных вам нужно extern (это необязательно для функций):

extern struct MyStruct g_myStruct;

Затем в файле реализации вы помещаете определения:

#include "Header1"

struct MyStruct g_myStruct;

int Foo(void){
    ...
}
person melpomene    schedule 10.09.2016
comment
@melpomene @barak manos Два правильных ответа одновременно. Спасибо. Знаешь, почему я должен это сделать? Это как старый C работал? Код в моем примере отлично работает с GCC, но в ILE я должен сделать то, что вы сказали. - person aganm; 10.09.2016
comment
@BobMarl: Что касается компилятора, каждый исходный файл является независимой единицей компиляции. Другими словами, компилятор не помнит ни одного предыдущего исходного файла, пока он работает с текущим исходным файлом. Однако компоновщик обнаруживает несколько определений одного и того же символа. Суть в том, что extern просто для того, чтобы компилятор знал, что переменная существует и где-то объявлена. Конечно, его еще нужно где-то объявить (создать экземпляр), и только один раз — иначе компоновщик выдаст ошибку. - person barak manos; 10.09.2016
comment
@BobMarl C работает по-прежнему так. Честно говоря, я не знаю, почему это работает в gcc. - person melpomene; 10.09.2016