Файл C/C++ перед предварительной обработкой

Можно ли просмотреть файл c/c++ перед предварительной обработкой? Или, скорее, после нерешительной предварительной обработки? В основном есть

#define <commonly_used_word> 0

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


person owagh    schedule 20.08.2012    source источник
comment
grep ‹commonly_used_word› ‹headerFile1› [‹headerFile2›]   -  person FrankieTheKneeMan    schedule 21.08.2012
comment
Ну, это скорее библиотека поставщика с несколькими местами, где это написано... Я хочу сосредоточиться на конкретном заголовочном файле, вызывающем эту проблему. (Да, это ужасная библиотека для работы)...   -  person owagh    schedule 21.08.2012
comment
В gcc есть опции для печати цепочки включения исходного файла. Это может помочь.   -  person Nicola Musatti    schedule 21.08.2012
comment
@NicolaMusatti Можете ли вы указать мне ресурс, который объясняет, как распечатать цепочку включения?   -  person owagh    schedule 21.08.2012
comment
@eq-: find /usr/include -name '*.h' -exec grep -P '^#define <commonword>' {} +. Пожалуйста, не оскорбляйте xargs.   -  person Michał Górny    schedule 21.08.2012


Ответы (4)


Ваш исходный файл является файлом перед предварительной обработкой.

Похоже, вы хотите, чтобы ваши директивы #include обрабатывались, но вы не хотите заменять макросы. Оба действия выполняются препроцессором.

В общем случае это невозможно, так как в C и C++ разрешено использовать макросы в качестве включаемых имен файлов, как в

#define INCLUDE_FILE "stdio.h"
#include INCLUDE_FILE 

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

Если вы хотите найти, где определен конкретный макрос, вы можете попробовать следующий прием: определить свой собственный макрос с тем же именем до включения любых заголовков и начать компиляцию. Компилятор (препроцессор) должен пожаловаться на переопределение макроса, когда он встретит библиотечное определение того же макроса и указать вам его местоположение.

person AnT    schedule 20.08.2012
comment
Имеет смысл... +1. Можно ли тогда просто распечатать цепочку включения, как предлагает Никола Мусатти? - person owagh; 21.08.2012
comment
Великолепно! Переопределение макроса точно определило это! Спасибо. - person owagh; 21.08.2012
comment
@AndreyT Что ты имеешь в виду под невозможно? Ему нужно запустить препроцессор на каком-то файле и получить предварительно обработанный файл, что абсолютно возможно, как упоминалось в других ответах. - person behnam; 21.08.2012
comment
@behnam: я не понимаю, что ты имеешь в виду. Запуск полного препроцессора удалит все операторы #define из единицы перевода. Это полностью разрушит цель того, что пытается сделать ОП. - person AnT; 21.08.2012
comment
@AndreyT: О, ты прав. Я неправильно понял вопрос. Спасибо. - person behnam; 21.08.2012

Существуют специфичные для GCC параметры -M и -MM:

Чтобы вывести абсолютные пути к включаемым файлам, используйте -M

Вместо вывода результата препроцессинга выведите подходящее для make правило, описывающее зависимости основного исходного файла. Препроцессор выводит одно правило make, содержащее имя объектного файла для этого исходного файла, двоеточие и имена всех включенных файлов, включая те, которые получены из параметров командной строки -include или -imacros. gcc -M test.c

Если вы не хотите, чтобы система включала подобные #include <stdio.h>, используйте -MM Like -M, но не упоминайте файлы заголовков, которые находятся в каталогах заголовков системы, а также файлы заголовков, которые прямо или косвенно включаются из такого заголовка. gcc -MM test.c

Это может значительно сузить область поиска.

http://www.math-linux.com/spip.php?article263

person vines    schedule 20.08.2012

Вы можете указать cpp сгенерировать список включенных файлов, используя опцию -M:

$ cpp -M a.c
a.o: a.c /usr/include/stdio.h /usr/include/features.h \
 /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
 /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \
 /usr/lib/gcc/x86_64-pc-linux-gnu/4.7.1/include/stddef.h \
 /usr/include/bits/types.h /usr/include/bits/typesizes.h \
 /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
 /usr/lib/gcc/x86_64-pc-linux-gnu/4.7.1/include/stdarg.h \
 /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h

Это дает вам формат правила Makefile, но вы можете игнорировать его и использовать с любой другой командой.

Например, вы можете найти символ (здесь я игнорирую stderr из-за того, что \ и a.o: не являются реальными именами файлов - лень):

$ grep '#\s*define\s*BUFSIZ' $(cpp -M a.c) 2>/dev/null
/usr/include/stdio.h:# define BUFSIZ _IO_BUFSIZ

Вы также можете использовать такую ​​программу, как ctags, чтобы найти символ для вас:

$ ctags $(cpp -M a.c)
...
$ grep BUFSIZ tags 
BUFSIZ  /usr/include/stdio.h    128;"   d
person Michał Górny    schedule 20.08.2012

Если вы знаете, какие файлы заголовков содержат определение, которое вы ищете, например, используя find и grep, как предложено, вы можете точно определить, какой из них влияет на текущий исходный файл, заставив gcc распечатать дерево включения заголовков. Как описано в документации gcc. , вы можете добиться этого, используя параметр -H, возможно, в сочетании с -MG, чтобы исключить нормальную обработку.

person Nicola Musatti    schedule 20.08.2012