Я разрабатывал на C, используя eclipse в качестве IDE на своей виртуальной машине с Ubuntu, я добился определенного прогресса и хотел протестировать их в реальном продукте, который представляет собой встроенную систему с использованием powerpc.
Чтобы скомпилировать эту программу для нашего продукта, я использую Code::Blocks в Windows, но компилятор представляет собой версию gcc для powerpc.
Тот же код дает мне ошибку в версии powerpc, которая не отображается в версии ubuntu.
У меня есть два файла заголовков гр.ч и module_hand.h следующим образом:
Файл гр.ч:
#ifndef HEADERS_GRAL_H_
#define HEADERS_GRAL_H_
#include "module_hand.h"
typedef struct PROFILE
{
module_t mod; // this one comes from module_hand.h
int var1; // some other random variables
} profile_t;
#endif /* HEADERS_GRAL_H_ */
module_hand.h определяется следующим образом
#ifndef HEADERS_MODULE_HAND_H_
#define HEADERS_MODULE_HAND_H_
#include <stdint.h>
#include "gral.h"
typedef struct PROFILE profile_t;
typedef struct module
{
char name[30]; // name of module
char rev[30]; // module revision
char mfr[30]; // manufacturer
} module_t;
int Mod_Init(profile_t *profile);
/* some other random functions */
#endif /* HEADERS_MODULE_HAND_H_*/
Как вы увидите, я не использую PROFILE struct
в module struct
, но я объявляю его вперед, чтобы использовать его в объявлении функции Mod_Init
.
Это дает мне Error: redefinition of typedef 'profile_t'
и error: previous declaration of 'profile_t' was here
Если я удалю предварительную декларацию, ошибка будет Error: parse error before '*' token
где номер строки — это строка объявления функции.
Я сомневаюсь, что мне не хватает, и почему gcc в Ubuntu компилирует его без проблем.
Что ж, у меня есть два файла c. Я включаю только файл Gral.h в свой main.c, однако в мой файл module_hand.c включены оба файла, причем файл Gral.h является первым.
Версия gcc для Ubuntu компилируется без проблем, поскольку оба определения эквивалентны.
Обратите внимание, что ваши два заголовка взаимно включают друг друга. Это всегда ужасная идея. Выясните, в каком порядке вы хотите, чтобы они были скомпилированы, и исправьте взаимное включение.
Вы получаете одинаковые ошибки для обоих файлов C?
Какие версии GCC вы используете? Какие варианты компиляции? В частности, вы используете опцию -std=
для любой сборки?
В заголовочном файле гр.ч вы определяете profile_t
с помощью typedef
, затем вы переопределяете profile_t
с другим typedef
в module_hand.h. Вы должны просто определить struct PROFILE
в gral_h и включить гр.ч в module_hand.h.
гр.ч:
#ifndef HEADERS_GRAL_H_
#define HEADERS_GRAL_H_
#include "module_hand.h"
typedef struct PROFILE {
module_t mod; // this one comes from module_hand.h
int var1; // some other random variables
} profile_t;
#endif /* HEADERS_GRAL_H_ */:
module_hand.h:
#ifndef HEADERS_MODULE_HAND_H_
#define HEADERS_MODULE_HAND_H_
#include <stdint.h>
typedef struct module
{
char name[30]; // name of module
char rev[30]; // module revision
char mfr[30]; // manufacturer
} module_t;
int Mod_Init(struct PROFILE *profile);
/* some other random functions */
#endif /* HEADERS_MODULE_HAND_H_*/
Ваш компилятор powerpc применяет правило C99, которое
If an identifier has no linkage, there shall be no more than one declaration of the identifier (in a declarator or type specifier) with the same scope and in the same name space, except for tags as specified in 6.7.2.3.
(С99 6.7/3)
Ваш компилятор Linux соблюдает смягченную версию этого правила, введенную в C11:
If an identifier has no linkage, there shall be no more than one declaration of the identifier (in a declarator or type specifier) with the same scope and in the same name space, except that:
- a typedef name may be redefined to denote the same type as it currently does, provided that type is not a variably modified type;
- tags may be redeclared as specified in 6.7.2.3.
(С11 6,7/3; также С17 6,7/3)
Если предположить, что параметры компиляции одинаковы, разница в поведении, безусловно, возникает из-за использования разных версий GCC. В более поздних версиях по умолчанию используются более поздние версии языка.
Вы можете попробовать добавить -std=gnu11
или -std=c11
к параметрам командной строки (для обеих целей), чтобы попытаться добиться согласованности. Если ваша версия GCC для powerpc слишком старая, чтобы принять их, вам действительно нужно обновиться до более новой версии.
Обратите внимание также, однако, что вам вообще не нужна эта проблема. Учитывая, что module_hand.h
включает gral.h
, первому нет необходимости переопределять typedef, который уже определен вторым.
Более того, тот факт, что каждый из этих двух заголовков включает в себя другой, убедительно свидетельствует о том, что их следует объединить в один. Защиты множественного включения предотвращают фактическую петлю, но они не являются адекватным решением.
Ну, я прочитал ваши ответы и комментарии и решил попробовать другой подход.
Как некоторые из вас сказали, у меня была какая-то рекурсия, я хотел сохранить каждую структуру в соответствующем заголовочном файле, но теперь я отказался от этой идеи и объединил структуры только в одном файле.
Мой новый подход:
Грал.ч
#ifndef HEADERS_GRAL_H_
#define HEADERS_GRAL_H_
typedef struct module
{
char name[30]; // name of module
char rev[30]; // module revision
char mfr[30]; // manufacturer
} module_t;
typedef struct PROFILE {
module_t mod; // this one comes from module_hand.h
int var1; // some other variables
} profile_t;
#endif /* HEADERS_GRAL_H_ */:
Модуль.h
#ifndef HEADERS_MODULE_HAND_H_
#define HEADERS_MODULE_HAND_H_
#include <Gral.h>
int Mod_Init(profile_t *profile);
/* some other functions */
#endif /* HEADERS_MODULE_HAND_H_*/
И когда появится любая другая структура, я объявлю ее в Gral.h и включу заголовочный файл.
Что касается компиляторов, они не той же версии. PowerPC уже довольно старый. Это объясняет ошибки компиляции powerpc.
Еще раз спасибо.
Какие из этих заголовков вы включаете в свой файл C? Если оба, то в каком порядке вы их включаете?