Используйте макрос, чтобы показать строковое содержимое макроса

Я пишу код для Arduino. Код становится длинным, поэтому я хочу использовать некоторые отладочные макросы и иметь возможность отображать некоторую отладочную информацию на последовательном порту.

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

#define SERIAL_GPS Serial1
#define SERIAL_IRIDIUM Serial2
#define SERIAL_VN100 Serial3

Как я могу написать макрос, чтобы показать порты, которые я использую для каждого из них? Т.е. какой-то макрос, который будет печатать на последовательном порту отладки:

Port for GPS: Serial1
Port for Iridium: Serial2
Port for VN100: Serial3

Я пытался:

#define SHOW_VAR_NAME(x) #x

вместе с:

SERIAL_DEBUG.println(SHOW_VAR_NAME(SERIAL_GPS));

Но это печатает на серийнике:

SERIAL_GPS

вместо:

Serial1

потому что (я полагаю) препроцессор макроса выполняет только одно сканирование. Какой-нибудь умный способ заставить это работать?

Примечание: здесь я беру простой пример, но есть некоторые переменные отладки (например, некоторые переменные DEBUG_GPS, DEBUG_IRIDIUM и другие), которые я действительно хотел бы распечатать при запуске платы: у меня довольно много таких параметров отладки для отдельных компонентов , а печать их статуса при запуске поможет отслеживать, какие отладки активированы или нет (даже если все они собраны в файле заголовка, не помешает запомнить пользователю обо всех из них).

Каждый раз, когда кто-то задает здесь макро-вопрос, я бы выделил предложение «посмотрите в зеркало и спросите себя, действительно ли нет лучшего способа».

UKMonkey 12.03.2018 13:36

@UKMonkey: Я все еще довольно близок к новичку, но чем больше я сталкиваюсь с макросами, тем больше я с вами согласен. Если у вас есть предложения по другому способу организации моего кода, мне будет очень интересно. Также обратите внимание, что это для плат Arduino, как написано в вопросе, то есть архитектура с примерно 32 КБ флэш-памяти и 1 КБ ОЗУ (в значительной степени зависит от того, какой конкретный MC). Это немного особые требования;)

Zorglub29 12.03.2018 13:40

Ну, не зная, что такое Serial1; Я собираюсь предположить, что это целое число, чтобы сообщить, какой порт Serial1 включен ... в этом случае создайте функцию с именем getPortUsage(int port), а затем вы можете switch(port) {case SERIAL_GPS: return "GPS";}. Это должно повлиять на использование памяти меньше, чем вы ожидали; особенно если вы встраиваете его или даже constexpr это

UKMonkey 12.03.2018 13:44

Нет, извините за то, что не предоставил больше контекста: это снова код Arduino со всеми вытекающими из него соглашениями;) Итак, если я прав, Serial1 - это полноценный последовательный объект (последовательный порт, управляемый прерываниями).

Zorglub29 12.03.2018 13:46

но я вижу логику в вашем методе;) (даже если это будет связано с некоторыми затратами по сравнению с макросом; переключатель не должен быть слишком плохим, но он быстро складывается на таких маленьких архитектурах, я думаю).

Zorglub29 12.03.2018 13:47

Оберните его в свой собственный объект, затем ... class GPSSerial { public: Serial& getSerial(){} const char* getName(){return "GPS";}

UKMonkey 12.03.2018 13:49

Тактовая частота 4 МГц ... оператор switch, вероятно, составляет 4-5 тактов. Миллион из них займет секунду. Сколько вы планируете сделать?

UKMonkey 12.03.2018 13:52

Не слишком много, вы правы. Если есть простое макро-решение, в качестве принятого ответа, мне оно нравится;)

Zorglub29 12.03.2018 13:53
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
8
78
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Оператор препроцессора # предотвращает раскрытие своего операнда. Вам нужно добавить уровень косвенного обращения, чтобы могло произойти расширение:

#define SHOW_VAR_NAME_(x) #x
#define SHOW_VAR_NAME(x) SHOW_VAR_NAME_(x)

Эта функциональность обеспечивается BOOST_PP_STRINGIZE от Boost.Preprocessor, который я рекомендую использовать, если вы начинаете интенсивно использовать препроцессор.

IOW, повторно внедрите BOOST_PP_STRINGIZE.

Angew is no longer proud of SO 12.03.2018 13:37

@Angew Я признаю себя виновным в FGITW. Я на самом деле сейчас беру документацию Boost.PP.

Quentin 12.03.2018 13:38

Большое спасибо как за ответ (это отлично работает), так и за указание на повышение. Как вы думаете, подойдет ли использование boost.preprocessor на контроллерах Arduino (обычно 32 КБ флэш-памяти, 1 КБ оперативной памяти), или это будет связано с некоторыми расходами?

Zorglub29 12.03.2018 13:44

@ Zorglub29 это все препроцессор, так что никаких следов :)

Quentin 12.03.2018 13:44

ок, спасибо :) Рассмотрим подробнее, когда у меня будет время;)

Zorglub29 12.03.2018 13:46

Строки могут быть сгенерированы препроцессором, но вы собираетесь что-то с ними делать. И как только они компилируются в окончательный исполняемый образ, остается является, занимающий память. При 1кБ ОЗУ даже крошечные струны могут оказаться стопорами для шоу.

IInspectable 12.03.2018 14:10

Другие вопросы по теме