Как структурировать мой c-код для создания функциональности - PullRequest
0 голосов
/ 01 марта 2019

Я новичок в языке программирования c и из другого поста увидел, что средства защиты заголовков не сохраняются, если файл заголовка включен в другой заголовок.Я думаю, это означает, что у меня возникли бы проблемы с переопределением символов, если бы я включил этот второй файл заголовка в третий заголовок.Я решил попробовать это, используя пример кода из другого поста, и да, я получаю ошибку.Я приложил код ниже.Возникает ли эта ошибка, потому что foo.h содержит определения, а не только объявления?Должно ли определение структур, определенных в foo.h, быть в foo.c?Если да, то какой подход я должен использовать, чтобы несколько модулей компиляции основывались на функциональности предыдущего?В стековой архитектуре, как слои получают доступ к функциональности предыдущего уровня (включают ли они заголовочные файлы или используют какой-то другой подход)?

/*
 * foo.h
 *
 */

#ifndef FOO_H_
#define FOO_H_

#include  "stdint.h"

uint8_t test();

typedef struct regVal{
    uint16_t add;
    uint8_t val;
}reg;

const struct regVal regArr[] =
 {
     {0x3103,0x03},
     {0x3008,0x82},
     {0xFFFF,0xFF}
 };

#endif /* FOO_H_ */

/*
 * foo.c
 */

#include "foo.h"
#include  "stdint.h"

uint8_t test();


uint8_t test(){
    return 0x01;
}

/*
 * foo2.h
 *
 */

#ifndef FOO2_H_
#define FOO2_H_

#include "foo.h"
#include  "stdint.h"



#endif /* FOO2_H_ */

/*
 * foo3.h
 *
 */

#ifndef FOO3_H_
#define FOO3_H_

#include "foo2.h"
#include "stdint.h"



#endif /* FOO3_H_ */

/*
 * foo3.c
 */

#include "foo3.h"
#include "stdint.h"

А вот ошибка компоновщика

 >symbol "regArr" redefined: first defined in "./foo.obj"; redefined in "./foo3.obj" null: symbol "regArr" redefined: first defined in "./foo.obj"; redefined in "./foo3.obj"

Ответы [ 2 ]

0 голосов
/ 01 марта 2019

Хорошо, позвольте мне сначала объяснить, что такое модуль компиляции.В c каждый отдельный файл .c компилируется отдельно для получения файла .o, а затем все файлы .o связываются для создания окончательного исполняемого файла.

Теперь давайте посмотрим, как обрабатываются включаемые файлы.Все включаемые файлы, включенные в ac-файл, копируются в этот c-файл на этапе предварительной обработки.Чтобы увидеть это, вы можете запустить gcc -E your-c-file.c -o out.i И вы можете проверить файл out, чтобы понять, что я имею в виду.

Так что, когда вы включаете foo.h в foo.c, он включается и на этапе компиляции создается экземпляр regArr [].Теперь, когда foo3.c скомпилирован, в этом модуле компиляции создается другой экземпляр regArr [], потому что в конечном итоге foo.h также включается в него.Обратите внимание, что все модули компиляции независимы.Теперь, когда компоновщик пытается связать оба объектных файла, он выдает эту ошибку, потому что в c две переменные или функции не могут иметь одинаковые имена.

0 голосов
/ 01 марта 2019

символ "regArr" переопределен: сначала определен в "./foo.obj";переопределено в "./foo3.obj" null: символ "regArr" переопределено: сначала определено в "./foo.obj";переопределено в "./foo3.obj"

в заголовках, вы просто должны объявлять переменные и функции, а не определять их (это возможно, если файл #included только один раз, но этоплохой выбор)

foo.h # * включается несколько раз, и каждый раз, когда вы определяете снова regArr

так что двигайся

const struct regVal regArr[] =
{
     {0x3103,0x03},
     {0x3008,0x82},
     {0xFFFF,0xFF}
};

int foo.c

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...