#c #c 11 #arduino #constexpr #undefined-reference
#c #c 11 #arduino #constexpr #неопределенная ссылка
Вопрос:
Я очень смущен тем, что здесь не так. Я получаю неопределенную ошибку ссылки на массив, который я определил так же, как и два других, которые не выдают ошибок в другом месте кода.
undefined reference to `shift7seg::numbers'
shift7seg.cpp код, показывающий другую функцию, использующую аналогичные используемые массивы
uint8_t shift7seg::convert_char(const charamp; OGchar){
uint8_t converted;
switch (OGchar){
case 'A':
converted = capital[0];
break;
case 'h':
converted = lower[3];
break;
//more cases removed for posting
}
return converted;
}
uint8_t shift7seg::convert_num(const uint8_tamp; OGnum){
uint8_t converted;
if(OGnum<10){
converted = numbers[OGnum];
}
else{
converted = blank;
}
return converted;
}
shift7seg.h, показывающий определения используемых массивов
class shift7seg{
public:
//constructor, choose pins to use as well as display size
shift7seg(const uint8_t _dataPin,
const uint8_t _latchPin,
const uint8_t _clkPin,
const uint8_t _num_digits);
static constexpr uint8_t numbers[10] = // 7 segment values for decimals 0..9
{
//TRUTH TABLE | 0 = segment on
//ABCDEFGH | 1 = segment off
B00000011, //0 | A
B10011111, //1 | -----
B00100101, //2 | F | | B
B00001101, //3 | | G |
B10011001, //4 | -----
B01001001, //5 | E | | C
B01000001, //6 | | |
B00011111, //7 | -----
B00000001, //8 | D
B00011001 //9 |
};
static constexpr uint8_t capital[13] =
{
B00010001, //A or R, 0
B00000001, //B 1
B01100011, //C 2
B00000011, //D or O, 3
B01100001, //E 4
B01110001, //F 5
B01000001, //G 6
B10010001, //H 7
B10000111, //J 8
B11100011, //L 9
B00110001, //P 10
B01001001, //S 11
B10000011 //U or V, 12
};
static constexpr uint8_t lower[9] =
{
B11000001, //b 0
B11100101, //c 1
B10000101, //d 2
B11010001, //h 3
B10011111, //l 4
B11010101, //n 5
B11000101, //o 6
B11110101, //r 7
B11000111 //u or v, 8
};
Диалект — C 11
Я ни за что на свете не смогу понять, что я сделал не так. Разговор с резиновой уткой пока ничего не дал.
Больше кода ошибки здесь .
more undefined references to `shift7seg::numbers' follow
collect2.exe: error: ld returned 1 exit status
exit status 1
Комментарии:
1. Разве вам не нужно определять статические переменные-члены вне самого определения класса?
2. Этот код должен быть абсолютно законным в C 17. Каков ваш диалект C ?
3. Похоже, что этот код компилируется на c 11, то есть это единственный компилятор, который я могу использовать в данном случае. как бы это выглядело, определяя статические переменные-члены в другом месте? Было бы это в моем driver.cpp и присваивать значения как глобальной переменной?
4. За исключением «constexpr» (C 11 или выше), я не вижу никаких причин, по которым это не должно компилироваться и связываться с ЛЮБОЙ версией C ! Вопрос: Возможно, один или другой из ваших объектных файлов, ссылающихся на «shift7seg», не был скомпилирован с C 11?
5. Я не знаком с этим типом ошибок, но я попытался скомпилировать его. Я получил одну дополнительную ошибку:
/usr/bin/ld: /tmp/cckpICDV.o: warning: relocation against '_ZN9shift7seg7numbersE' in read-only section '.text'
. Код становится способным к компиляцииOGnum
, когда вы меняетеnumbers
доступ к массиву на некоторую константу like2
, однако он также компилируется при переходе на C 17.
Ответ №1:
Где-то в вашем коде вы используете ODR numbers
, но у вас нет определения для этого.
Вот простая версия вашей проблемы (wandbox):
#include <iostream>
#include <cstdint>
class shift7seg {
public:
static constexpr std::uint8_t numbers[10] = {};
};
int main() {
// taking the address is ODR-use
std::cout << amp;shift7seg::numbers[0] << 'n';
}
Возможные решения
- скомпилируйте с
-std=c 17
помощью (или более поздней версии), где всеstatic constexpr
элементы данных являются неявнымиinline
и не требуют внесистемных определений - Добавьте нестандартное определение в свой файл реализации (shift7seg.cpp ) вот так (коробка для волшебных палочек):
constexpr std::uint8_t shift7seg::numbers[10];
Комментарии:
1. Похоже, что это проблема, добавление нестандартного определения устранило эту ошибку и привело к появлению других. отладка продолжается, спасибо
Ответ №2:
Прежде всего, я думаю, что префикс находится 0B
в этих двоичных литералах, а не B
. Во-вторых, вам нужен c 17 для его компиляции из-за статического содержимого constexpr.
Цитата
Если статический элемент данных объявлен constexpr, он неявно является встроенным и не нуждается в повторном объявлении в области пространства имен. Это повторное объявление без инициализатора (ранее требовалось, как показано выше) по-прежнему разрешено, но устарело.
Комментарии:
1. это весь код для arduino, поэтому правильный двоичный буквальный тег — B я посмотрю, смогу ли я заставить его работать без constexpr