Общие константы для проекта AVR/Linux GCC C++

Я создаю программное обеспечение для проекта Linux + AVR Arduino. Очевидно, что вся работа разделена на несколько проектов в Eclipse (я не использую Arduino IDE). Я хотел бы использовать общие, в основном строковые, константы для всех этих проектов. Я также должен сэкономить оперативную память микроконтроллера, поэтому необходимы константы времени компиляции. Как мне лучше всего это реализовать? Моя идея состоит в том, чтобы создать отдельный проект только для заголовков для этих констант.

С использованием:

class A {
public:
    static const char * const STRING;
    static const unsigned char BOOL;
};

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

class A {
public:
    static const char * const STRING_PART1;
    static const char * const STRING_PART2;
    static const unsigned char BOOL;
};
const char * const A::STRING_PART1 = "PART1_";
//const char * const A::STRING_PART2 = A::STRING_PART1 + "PART2"; //obviously won't compile
//const char * const A::STRING_PART2 = strcat("PART2", A::STRING_PART1); //this is not compile-time

Я также не хочу использовать define. Я хотел бы использовать:

class A {
public:
    static const std::string STRING_PART1;
    static const std::string STRING_PART2;
}

который допускает конкатенацию строк и является (AFAIK) временем компиляции, но std::string недоступен в проектах avr - или я здесь ошибаюсь и просто не знаю, как его использовать.

Любая помощь приветствуется.


person mmm    schedule 07.09.2011    source источник


Ответы (2)


Вы можете продолжить текущую идею использования const char* const (если std::string использовать нельзя). Я бы предложил использовать #define только для назначения. Пример:

class A {
public:
    static const char * const STRING_PART1;
    static const char * const STRING_PART2;
    static const unsigned char BOOL;
};
#define PART1_ "PART1_"  // <--- for value assignent
#define PART2_ "PART2_"
const char * const A::STRING_PART1 = PART1_;
const char * const A::STRING_PART2 = PART1_ PART2_;  // <--- ok! concatenation by compiler
person iammilind    schedule 07.09.2011
comment
Спасибо iammilind, это компилируется, но: я не хочу загрязнять глобальное пространство имен определениями (да, я мог бы отменить их определение после инициализации, но это не чисто ИМХО), и в основном вторая константа не является временем компиляции (просто проверил, что добавление добавляет 16 байт к общему использованию памяти, не знаю, почему 16). - person mmm; 07.09.2011
comment
@ ммм, конечно, вторая константа находится во время компиляции. Это добавит использование памяти, потому что теперь у вас есть 2 строки. "PART1_" и "PART1_PART2_"; размер второй строки 14 байт. Если бы это было не во время компиляции, это была бы ошибка компилятора. - person iammilind; 07.09.2011
comment
хм, либо я не понимаю, что означает константа времени компиляции, либо вы ошибаетесь, но я пока этого не предполагаю. Для меня константа времени компиляции означает, что она не использует оперативную память во время выполнения, потому что она жестко закодирована компилятором. Ваше решение, даже если это кажется нелогичным, использует оперативную память во время выполнения в соответствии со статистикой avr-g++, отображаемой при компиляции. Там написано: Программа: 97362 байта (74,3% заполнения) Данные: 7660 байт (93,5% заполнения), тогда как без второй константы данных на 16 байт меньше. Первый добавляет только 2 байта, чего я тоже пока не понимаю, предполагая, что это всего лишь размер основного указателя. - person mmm; 07.09.2011
comment
@ ммм, постоянная времени компиляции не означает, что она не использует память. Без памяти где он будет храниться? Он должен храниться в какой-то области памяти, и это решает компилятор. - person iammilind; 07.09.2011
comment
Время компиляции для меня означает, что оно хранится в ПЗУ (например, во флэш-памяти микроконтроллера), тогда как переменные времени выполнения хранятся в ОЗУ. В моем случае это оперативная память, которую я должен сэкономить. Компилятор решает, куда поместить переменные, основываясь на множестве правил. Определения являются одним из примеров констант времени компиляции, они явно не учитываются при использовании оперативной памяти. Другим примером должны быть статические константы класса, но в этом случае мой компилятор решает иначе. Конечно, я могу что-то путать. - person mmm; 07.09.2011
comment
Хорошо, после более длительного тестирования я должен признать, что был частично неправ. Компилятор помещает переменную в оперативную память до тех пор, пока она не используется (и в моих тестах до того, как я не использовал вторую, я просто объявил ее). Когда на него ссылаются в коде, он перемещается в ПЗУ. Странны пути оптимизации компиляторов. Еще раз спасибо iammilind. Но есть еще одна проблема: если будут константы, которые я буду использовать только в проекте AVR, я потрачу оперативную память. Так что это, к сожалению, не решение моей проблемы. - person mmm; 07.09.2011

Время компиляции для меня означает, что оно хранится в ПЗУ (например, во флэш-памяти микроконтроллера), тогда как переменные времени выполнения хранятся в ОЗУ. В моем случае это оперативная память, которую я должен сэкономить. Компилятор решает, куда поместить переменные, основываясь на множестве правил. Определения являются одним из примеров констант времени компиляции, они явно не учитываются при использовании оперативной памяти. Другим примером должны быть статические константы класса, но в этом случае мой компилятор решает иначе. Конечно, я могу что-то путать.

Я думаю, что вы на самом деле путаете вещи:

  • определения не хранятся в ПЗУ - они вообще не являются частью вашей программы, поскольку они уже оцениваются препроцессором.
  • разница между «временем компиляции» и «временем выполнения», которое вы делаете, относится к оценке, а не к хранению.

Если вы хотите использовать программную память (= AVR flash) для постоянных строк, используйте макрос PSTR из avr/pgmspace.h.

person hackotronic    schedule 07.09.2011
comment
Под ПЗУ я имел в виду, что определения оцениваются и переводятся в двоичную форму и, как таковые, хранятся внутри скомпилированного исходного кода. Так что, думаю, я не путаю, просто, возможно, неправильно называю. Я пытаюсь добиться того, чтобы константы хранились в хорошем, gcc и avrgcc-совместимом виде, а не тратили на это оперативную память. - person mmm; 07.09.2011
comment
да, #define не преобразуются в двоичные файлы - на самом деле, компилятор вообще их не видит, потому что препроцессор их уже оценивает. Компилятор увидит то же самое, если вы напишете foo или FOO, если вы #define FOO foo. - person hackotronic; 07.09.2011
comment
<avr/pgmspace.h> и PSTR("foo") — это именно то, что вы хотите использовать, если у вас больше флэш-памяти, чем оперативной памяти. - person hackotronic; 07.09.2011
comment
обратитесь к руководству по данным в программном пространстве: nongnu.org/avr-libc /user-manual/pgmspace.html - person hackotronic; 07.09.2011