Использование макропеременной C в #include

У меня есть файл кода C, содержащий следующее:

#include MYHEADER

Я знаю, что такое включение переменных — плохая практика, но это не мой код, я просто хочу его скомпилировать. Я хочу, чтобы переменная MYHEADER имела значение <some_header.h>, а не "some_header.h". Я пробовал множество способов передать это, но пока ни один из них не помог.

Например. arm-none-eabi-gcc -c -DMYHEADER=<some.h> -o sample.o sample.c не работает, Я всегда получаю ошибку: #include expects "FILENAME" or \<FILENAME\>. Использование компилятора ARM GCC в Windows.

Пожалуйста, порекомендуйте.

почему ты хочешь сделать это? В чем проблема XY?

Chris 14.03.2024 00:40

@Chris Крис Это не его собственный код.

Barmar 14.03.2024 00:48

Это невозможно с препроцессором C. Я подозреваю, что файл должен быть обновлен с помощью какого-то другого инструмента.

Barmar 14.03.2024 00:48
#define MYHEADER <stdio.h> ... #include MYHEADER компилируется с помощью MS VC. Но #define MYHEADER stdio.h... #include <MYHEADER> нет.
Weather Vane 14.03.2024 00:52

TL;DR: Нет (и я пробовал много раз ;-) Обратите внимание, что "some_header.h" работает с трюком MYHEADER. Но IIRC <some_header.h> не будет. Но единственная разница состоит в том, что "some_header.h" будет сканировать текущий каталог в поисках some_header.h, прежде чем делать то, что будет делать <some_header.h>: искать в каталогах -I, искать в некоторых «стандартных» каталогах (например, /usr/include). Итак, если в текущем каталоге (при компиляции) нет some_header.h, разницы нет.

Craig Estey 14.03.2024 00:53

Создайте файл indirect_some_header.h, содержащий (только) #include <some_header.h>, а затем используйте -DMYHEADER = "indirect_some_header.h" (с соответствующими escape-символами для кавычек для вашей оболочки)

Chris Dodd 14.03.2024 01:00

@Barmar: «Это невозможно с препроцессором C»: Да, это возможно. В C 2018 6.10.2 4 говорится: «Директива предварительной обработки формы ##include pp-tokens new-line (которая не соответствует ни одной из двух предыдущих форм) разрешена. Токены предварительной обработки после include в директиве обрабатываются так же, как и в обычном тексте. (Каждый идентификатор, определенный в настоящее время как имя макроса, заменяется списком замещающих токенов предварительной обработки.)…»

Eric Postpischil 14.03.2024 01:10

Рассматривает ли ваш процессор командной строки < и > как перенаправление файлов? Что произойдет, если поставить -DMYHEADER=<some.h> в кавычки?

Eric Postpischil 14.03.2024 01:11

проверьте свою папку, там будет файл с именем -o, и gcc получит входные данные от какого-то, возможно, несуществующего some.h и проигнорирует его

phuclv 14.03.2024 01:42

@phuclv: Если some.h не существует, оболочка должна сообщить об этом как об ошибке и не выполнять команду. Вероятно, у них в каталоге есть файл some.h.

Eric Postpischil 14.03.2024 03:08
Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
10
87
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

Сообщение, которое вы получаете, создается GCC, если MYHEADER определен как пустой (в его списке замены нет токенов). Если процессор командной строки (также называемый оболочкой), который вы используете, принимает <some.h> для обозначения перенаправления файла, где < указывает на получение входных данных от some.h, а > принимает следующий за ним -o для обозначения записи в -o, то он оставляет -DMYHEADER= с пустой список замены.

Если это так, исправлением может быть цитирование переключателя:

arm-none-eabi-gcc -c "-DMYHEADER=<some.h>" -o sample.o sample.c 

Вот два теста в дополнение к использованию приведенной выше команды:

  • Проверьте, есть ли в вашем каталоге файл с именем -o. Если это так, то это было создано косвенно, подтверждая, что именно это и происходит.

  • Создайте файл с именем x.c, поместите в него MYHEADER (и ничего больше) и выполните arm-none-eabi-gcc -E x.c -DMYHEADER=<some.h>. Если процессор командной строки жалуется на отсутствие имени файла после >, это подтверждает гипотезу. Если он выполнит команду или если он выполнит команду после того, как вы добавите, скажем, foo после >, выходные данные покажут, на что заменяется MYHEADER. (Переключатель -E запрашивает предварительную обработку, поэтому единственная строка, содержащая MYHEADER, будет заменена пустой строкой, если -DMYHEADER= будет передана в GCC.)

Одна из проблем с этой гипотезой заключается в том, что процессор командной строки должен был сообщить, что не может открыть some.h для перенаправления ввода. Но, возможно, у вас в каталоге есть файл с таким именем, который удовлетворит процессор командной строки.

Другая возможность заключается в том, что стандарт C не полностью определяет, как обрабатываются токены, полученные в результате замены макроса в #include. Когда <name.h> появляется непосредственно в #include, он обрабатывается специальным грамматическим токеном — последовательностью h-символов. Когда вместо этого используется замена макроса, в стандарте C 2018 6.10.2 4 говорится:

… Метод, с помощью которого последовательность токенов предварительной обработки между парой токенов предварительной обработки < и > или парой символов " объединяется в один токен предварительной обработки имени заголовка, определяется реализацией.

Я не думаю, что проблема в этом, поскольку тест Compiler Explorer показывает, что GCC обрабатывает замену MYHEADER на <stdio.h> обычным подходящим способом.

Спасибо, Эрик, я бы этого не понял.

T. Jastrzębski 14.03.2024 08:59

Добавление #define MYHEADER <some_header.h> перед #include MYHEADER может сработать. или Если у вас много таких, вы можете поместить все #define в файл file.txt и #include этот файл.txt перед использованием #inclue MYHEADER.

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