Оценка define(x) в выходной строке `#pragma message`

В целях отладки я пытаюсь вывести информацию о том, определены ли определенные символы, но без необходимости ухудшать читаемость кода слишком большим количеством блоков #if defined(). Я попробовал использовать оператор defined() при выводе текста с помощью #pragma message вот так:

#pragma message defined(__UNDERLAY__)

Я ожидал, что на выходе будет 1, если __UNDERLAY__ определен, и 0, если нет. Но вместо этого:

testbed_defines.c:61:9: warning: expected a string after ‘#pragma message’ [-Wpragmas]
   61 | #pragma message defined(__UNDERLAY__)
      |         ^~~~~~~

Я попытался "строчить" вот так:

#pragma message "" defined(__UNDERLAY__)

Это вызвало только другую ошибку:

testbed_defines.c:61:9: warning: junk at end of ‘#pragma message’ [-Wpragmas]
   61 | #pragma message "" defined(__UNDERLAY__)
      |         ^~~~~~~

Я попробовал оператор конкатенации:

testbed_defines.c:61:20: error: stray ‘##’ in program
   61 | #pragma message "" ## defined(__UNDERLAY__)
      |                    ^~
testbed_defines.c:61:9: warning: junk at end of ‘#pragma message’ [-Wpragmas]
   61 | #pragma message "" ## defined(__UNDERLAY__)
      |         ^~~~~~~

Есть ли способ вывести значение defined(x) без необходимости создания блока #if? Тем более, что для этого мне нужно будет записать два допустимых значения (0 и 1) в код, как магические числа. Похоже, defined здесь вообще не оценивается!

Почему бы не поставить #pragma внутри #ifdef?

pts 08.08.2024 15:14

Pragma во многом зависит от компилятора. Некоторые компиляторы расширяют сообщения, некоторые нет. Разные компиляторы делают это по-разному. Какой компилятор вы используете?

KamilCuk 08.08.2024 15:23

@pts Когда таких блоков для проверки много, большое количество блоков #ifdef ... #endif ухудшит читаемость кода. И, как я уже упоминал, мне бы хотелось избежать жесткого кодирования допустимых выходных значений define() как магических чисел.

AJM 08.08.2024 15:25

@KamilCuk Хорошая мысль. Я использую gcc и только что добавил тег [gcc] для пояснения.

AJM 08.08.2024 15:26

«Есть ли способ вывести значение define(x) без необходимости создания блока #if?» Нет.

n. m. could be an AI 08.08.2024 15:30

@n.m.couldbeanAI Раздел 6.10.1 проекта C11 (N1570) описывает defined(), но ничего не говорит о том, что он должен находиться в блоке #if. Можете ли вы привести источник, подтверждающий ваше утверждение?

AJM 08.08.2024 15:40

Вы можете использовать любой идентификатор где угодно. Это просто не будет иметь того же значения, что и в блоке #if. Раздел, на который вы ссылаетесь, описывает значение defined, используемого в блоке #if. За пределами одного это просто обычный идентификатор.

n. m. could be an AI 08.08.2024 15:50
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
7
50
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

Есть ли способ вывести значение define(x) без необходимости создания блока #if?

Нет. defined() оценивается только внутри #if, #elif и тому подобного.

Вы можете проверить, расширяется ли макрос до нуля, с помощью https://gustedt.wordpress.com/2010/06/08/detect-empty-macro-arguments/ .

Невозможно расширить до 1 или 0 в зависимости от того, определен ли макрос Есть ли способ преобразовать переменный макрос в 0 или 1 в зависимости от того, определен ли он? .

У вас есть источник для этого? Раздел 6.10.1 проекта C11 (N1570) описывает defined(), но ничего не говорит о #if или #ifelse.

AJM 08.08.2024 15:37

@AJM: Если вы видели defined, описанный в C 2011 6.10.1, вы видели заголовок этого пункта: «Условное включение». В этом пункте описывается исключительно функция условного включения предварительной обработки, то есть директивы #if, #ifdef, #ifndef, #elif, #else и #endif. Предложение, описывающее defined, начинается со слов «Выражение, управляющее условным включением, должно быть…», и именно в этом контексте описывается defined. Это происходит исключительно в контексте выражения, управляющего условным включением.

Eric Postpischil 08.08.2024 15:43

@AJM: По поводу «… 6.10.1 … но ничего не говорится о #if или #ifelse»: Это странно. Во-первых, это #elif, а не #ifelse. Во-вторых, 6.10.1 содержит шесть параграфов. Упоминания #if встречаются в абзацах 3, 4 и 5.

Eric Postpischil 08.08.2024 15:45

@EricPostpischil Чтобы уточнить, в пункте 1 раздела 6.10.1 описывается defined(), но не упоминаются #if или #ifelse. Остальные абзацы не описывают defined. Я бы вернулся и отредактировал этот комментарий с этим пояснением, но сейчас у меня истек 5-минутный лимит.

AJM 08.08.2024 15:47

Снова подумав о абзацах 3 и 5 в свете вашего комментария... действительно начинает казаться, что я не могу этого сделать и мне придется принять этот ответ и двигаться дальше.

AJM 08.08.2024 15:49

@EricPostpischil Кроме того, я упомянул #ifelse, потому что об этом упоминалось в ответе. Я этого не узнал, но, по крайней мере, смог сказать, что в этой части C11 об этом не упоминалось.

AJM 08.08.2024 15:50

Извините, ничего умного вы не можете сделать. Лучшее, что вы можете сделать, это

#ifdef __UNDERLAY_\
    #pragma message “__UNDERLAY is defined”
#else
    #pragma message “__UNDERLAY__ is not defined”
#endif

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

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