Вопрос по include, macros, c, c-preprocessor –  или же

9

аюсь выяснить, как создать переменную строку для оператора #include с помощью GCC.

Идея состоит в том, что для каждого написанного мной исходного модуля я хочу включить в качестве заголовка динамически генерируемыйC источник, который был создан ранее в процессе сборки.

Создание этого файла не является проблемой. В том числе и это, к сожалению, есть.

То, что у меня пока есть, - это: identity.h:

// identities.h

# define PASTER2(str)  #str
# define PASTER(str)   PASTER2(str ## .iden)
# define EVALUATOR(x)  PASTER(x)

# define IDENTITIES_FILE EVALUATOR(__FILE__)
# include IDENTITIES_FILE

В идеале это можно использовать так (main.c):

//main.c

# include "identities.h"

int main() {return 0;}

Который был бы расширен за один проход препроцессором перед компиляцией, чтобы привести к:

//main.c (preprocessed)

# include "main.c.iden"

int main() {return 0;}

Два уровня косвенности, которые я использую (PASTER и EVALUATOR), являются результатомэто Почта.

К сожалению, это не работает, и я остаюсь с ошибкой:

obj/win32/dbg/main.o
In file included from main.c:1:0:
identities.h:42:1: error: #include expects "FILENAME" or <FILENAME>

Я думаю, проблема в том, что в операторе включения отсутствуют кавычки. Есть идеи?

Если у вас есть «динамически генерируемый источник C», то можете ли вы динамически генерировать новый заголовочный файл из всех заголовочных файлов, которые вы хотите включить? Хотя мне все еще любопытно посмотреть, возможно ли сделать то, что ты хочешь сделать. leetNightshade
@leet: Нет, проблема требует абсолютно минималистского подхода к модификации текущей системы сборки. Было решено, что мы попытаемся сделать это, отредактировав каждый файл так, чтобы он включал один общий заголовок "identityities.h" - и только этот один файл. J T
@AlexandreC. Странно, я могу это сделать. Я не должен существовать в вашей вселенной ;-). Я думаю, что вы имели в виду, вы не можете сделать это сстандарт C / C ++. artless noise
Короткий ответ: вы не можете сделать это, точка. Alexandre C.

Ваш Ответ

5   ответов
3

что вы не можете делать то, что хотите, __FILE__ возвращает строку, а ## работает с токенами, и отсутствует макрос препроцессора concat для строки CPP. Обычно это достигается благодаря тому, что две строки подряд, например,

"Hello" " World"

будет обрабатываться синтаксическим анализатором C ++ как одна строка, однако #include является частью препроцессора и поэтому не может воспользоваться этим фактом.

Старый ответ:

Почему вы это делаете

{ #str, str ## .iden }

Я уверен, что это не синтаксис препроцессора, что вы надеетесь достичь через это? Вы пробовали только что:

str ## .iden

«{» Может объяснить ошибку, которую вы получаете.

К сожалению, я попробовал последний подход ранее и получил ту же ошибку. Подход, который я использую, взят из документации GCC:tigcc.ticalc.org/doc/cpp.html#SEC18 J T
Woops, ты прав. Виноват! J T
Смотрите мое новое редактирование. Arelius
-1

как это. Вы должны указать имя файла для директивы #include, это не может быть какой-то другой макрос.

Извиняюсь за то, что не пометил, хотя я и заявил в вопросе, что я использую GCC. J T
На самом деле «компьютерные включения» (или некоторые их формы) допускаются стандартом C - стандартом C99. См. 6.10.2 / 4 ..."# include pp-tokens newline" где pp-токены должны расширяться до одного из<header> или же"header-file" pmg
@JT Это «особенность» препроцессора GCC - он не является частью стандартов C или C ++ для предварительной обработки. Neil Butterworth
@ JT, На самом деле он в достаточной степени прав, вычисленные включения являются расширением GCC, и вы не отметили свой вопрос как только GCC. Blindy
Я знаю, что это неправильно (поиск "Computed Includes"):tigcc.ticalc.org/doc/cpp.html J T
1

Boost препроцессорная библиотека , Это специально сделано, чтобы добавить кавычки вокруг имени.

BOOST_PP_STRINGIZE не просто добавляет фунт #. В документе, в частности, сказано, что, в отличие от простого использования #, этот макрос фактически позволяет расширять свой аргумент (а # не делает). После нескольких тестов кажется, что ваша главная проблема в том, чтоФАЙЛ расширяется до имени файла, которое уже находится в кавычках, и удалить их невозможно (по крайней мере, насколько я знаю). Mikael Persson
+1 за повышение ссылок ognian
К сожалению, все, что это делает, это добавляет фунт перед текстом: "# define BOOST_PP_STRINGIZE_I (text) #text" J T
@Mikael: Вы правы, я сам пришел к такому выводу. J T
Да, я прибег к использованию GCC и Make: gcc -c -DEVALUTOR_ARGUMENT = $ <$ < J T
7

Видетьстрока 100 из compiler-gcc.h.

#define __gcc_header(x) #x
#define _gcc_header(x) __gcc_header(linux/compiler-gcc##x.h)
#define gcc_header(x) _gcc_header(x)
#include gcc_header(__GNUC__)

Я пытаюсь выяснить, как создать переменную строку для оператора #include с помощью GCC.

Этот токен вставляет значение__GNUC__ в строку; "Linux / компилятор GCC"__GNUC__ ".h", а затем приводит в соответствие результат. Это может бытьНКУ расширение препроцессора.

Вот пример,

t1.h
#define FOO 10
t2.h
#define FOO 20
a.c
#ifndef VERSION
#define VERSION 1
#endif
#define __gcc_header(x) #x
#define _gcc_header(x) __gcc_header(t##x.h)
#define gcc_header(x) _gcc_header(x)
#include gcc_header(VERSION)
#include <stdio.h>

int main(void)
{
        printf("FOO is %d\n", FOO);
        return 0;
}

Вот две компиляции,

g++ -o a a.cc
g++ -DVERSION=2 -o a a.cc

Результат любой компиляции дает ожидаемый результат.

Как и в случае с исходным кодом Linux, вы можете отключить предопределенные значения gcc.echo | g++ -dM -E - даст список.

Для вашего случая вы можете использоватьMakefile передать определение компиляции, чтобы позволить динамическое включение сгенерированного заголовка без изменения источника. Но тогда простой альтернативой является просто запуститьsedи т. д. в исходном файле шаблона и замените его известным именем include.

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

Linux объединил файлы и просто использует условия препроцессора, чтобы проверить это сейчас. Вотссылка на старую версию, Другая возможностьрасширения has_include как в новом GCC, так и в лязге. artless noise
Вы не можете использовать__FILE__ конечно, как указали другие. В C ++ и более поздних версиях C это указатель, а не строковый литерал (согласноarelius). artless noise
0

я не понимаю, что пытается сделать ваш код. Ты говоришь:

# define PASTER(str)  { #str, str ## .iden }

Вы даете этоmain.c и ожидать"main.c.iden"но это возвращает{"main.c", main.c.iden }.

Вместо этого вы ищете это?

#define PASTER2(str) #str
#define PASTER(str) PASTER2(str ## .iden)
Вы правы, и я изменил его, хотя, к сожалению, он выдает ту же ошибку .. J T

Похожие вопросы