Символ "файл @ переменная" определен более одного раза
IDE: MPLAB X v2.15
CC: XC8 v1.32
Целевое устройство: PIC18f45k20
У меня есть заголовочный файл reg.h
, который содержит переменную
static const int aaasdf = 3;
Этот заголовок имеет правильное включение охранников в начале:
#ifndef PRJ_REG_H
#define PRJ_REG_H
И в конце:
#endif
Если у меня есть та же самая переменная в любом другом заголовочном файле, она прекрасно компилируется, но когда эта переменная находится в этом конкретном файле, она дает мне error: (845) symbol "reg@aaasdf" defined more than once
Но если я прокомментирую эту переменную, она больше не будет существовать и будет жаловаться, потому что она мне нужна в каком-то файле.c.
Странное имя только для тестирования, чтобы убедиться, что нет другой переменной с таким же именем.
Что еще я могу сделать, чтобы отладить это?
РЕДАКТИРОВАТЬ:
Это делает для любого static const
переменная, (завтра проверю только static
, const
или же extern const
), что я создаю в этом файле, но есть и enum
с и static inline
функции, и ни одна из них не дает мне повторную ошибку символа.
РЕДАКТИРОВАТЬ:
Я думаю, что это компилятор, который сломан:
Я удалил все из шапки, а также исходные файлы. Теперь main - это бесконечный цикл, и все так.
Заголовки пусты, но для переменной, вызывающей ошибку.
Ни один мой заголовок не содержит никакого другого моего заголовка.
Что вызывает ошибку: любой заголовок, который включен во многие исходные файлы и содержит static const
переменная любого типа. Под многими я подразумеваю, что, если я включаю заголовок только в его исходный файл и другой файл, он не вызывает ошибку, но если он включен в 2 исходных файла, которые не являются его исходным файлом, он вызывает ошибку,
РЕДАКТИРОВАТЬ:
Как и требовалось, вот MCV-пример того, что я хочу (не ошибка компиляции):
// reg.h
enum Reg_OSCCON_IRCF_Values {
REG_OSCCON_IRCF_FREQ_31_KHZ = 0x0u,
REG_OSCCON_IRCF_FREQ_250_KHZ = 0x1u,
REG_OSCCON_IRCF_FREQ_500_KHZ = 0x2u,
REG_OSCCON_IRCF_FREQ_1_MHZ = 0x3u,
REG_OSCCON_IRCF_FREQ_2_MHZ = 0x4u,
REG_OSCCON_IRCF_FREQ_4_MHZ = 0x5u,
REG_OSCCON_IRCF_FREQ_8_MHZ = 0x6u,
REG_OSCCON_IRCF_FREQ_16_MHZ = 0x7u
};
#define REG_OSCCON_IRCF_FREQ ((const uint32_t [8]){ \
31000u, \
250000u, \
500000u, \
1000000u, \
2000000u, \
4000000u, \
8000000u, \
16000000u \
})
static inline void reg_field_set(volatile uint8_t *reg,
uint8_t mask, uint8_t posn, uint8_t val)
{
*reg = (*reg & ~mask) | ((val << posn) & mask);
}
static inline void reg_OSCCON_IRCF_set(uint8_t val)
{
reg_field_set(&OSCCON, _OSCCON_IRCF_MASK, _OSCCON_IRCF_POSN, val);
}
// pwm.c
#include "reg.h"
extern uint32_t sys_freq;
int foo(/**/)
{
static const uint32_t freq_min =
REG_OSCCON_IRCF_FREQ[REG_OSCCON_IRCF_FREQ_16_MHZ] /
(UINT8_MAX * 4 *
REG_T2CON_T2CKPS_PRESCALER[REG_T2CON_T2CKPS_PRESCALER_1]);
reg_OSCCON_IRCF_set(REG_OSCCON_IRCF_FREQ_16_MHZ);
sys_freq = REG_OSCCON_IRCF_FREQ[REG_OSCCON_IRCF_FREQ_16_MHZ];
// ...
}
Вариант 1: как показано выше, используя макрос, который расширяется до const
составной массив литерал, где я могу получить доступ к любому из его элементов (во время компиляции или во время выполнения). Необходимость C99
которого у меня нет. РЕДАКТИРОВАТЬ: const
составные литералы могут быть или не быть константными выражениями ( Инициализировать статическую переменную с элементом составного литерала const), и поэтому могут быть или не быть допустимыми в качестве инициализаторов для static
переменные.
Вариант 2: изменение макроса на static const
массив. Плюсы: не нужны C99
, Минусы: НЕ МОЖЕТ инициализировать static
переменная. Компилятор кажется сломанным и не позволяет мне это делать.
Вариант 3: Магические числа. Плюсы: не нужны C99
, Можно инициализироватьstatic
переменная. Минусы: магические числа.
Вариант 4: много макросов (для каждого из массивов, потому что он не только этот!). Плюсы: не нужны C99
, Минусы: загрязнение глобального пространства имен.
1 ответ
Определенно XC8
компилятор не работает.
Сегодня подобные ошибки появились при использовании static inline
функции. Я гуглил об этом, и кажется, что компилятор не очень хорош с таким кодом.