или же

аюсь выяснить, как создать переменную строку для оператора #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>

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

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

Ответы на вопрос(5)

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

"Hello" " World"

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

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

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

{ #str, str ## .iden }

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

str ## .iden

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

 J T03 мая 2011 г., 20:21
К сожалению, я попробовал последний подход ранее и получил ту же ошибку. Подход, который я использую, взят из документации GCC:tigcc.ticalc.org/doc/cpp.html#SEC18
 J T03 мая 2011 г., 20:23
Woops, ты прав. Виноват!
 Arelius03 мая 2011 г., 20:59
Смотрите мое новое редактирование.
Решение Вопроса

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

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

Видетьстрока 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, это может быть их единственным выбором.

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

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

# 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 T03 мая 2011 г., 20:24
Вы правы, и я изменил его, хотя, к сожалению, он выдает ту же ошибку ..

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

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

Ваш ответ на вопрос