2012-11-21 10 views
5

przestrzegać następujący program:# include plik pochodzący z makra __FILE__?

#include __FILE__ 
main(){} 

Preprocesor utknie w nieskończonej rekurencji wraz z kopią sobie wewnątrz siebie i narzekają main() już zdefiniowany.


Jeśli mogę używać makr zawierać pliki mogę czerpać nazwę pliku w oparciu o __FILE__ i umieścić go?


Na przykład, chciałbym to "foo.h" podczas gdy wewnątrz "foo.cpp", ale wywodzą ją od __FILE__.

  • ## połączy makra.
  • Możliwe jest również stosowanie makr Stringify.

Czy można to zrobić za pomocą preprocesora?

+1

Nie można edytować nazwy pliku, a konkatenacja sąsiednich literałów łańcuchowych występuje w fazie 6 tłumaczenia, ale wstępne przetwarzanie odbywa się w fazie 4, więc nie można używać łączenia ciągów. Oznacza to, że nie można zbudować nazwy pliku, który może być włączony przez preprocesor z '__FILE__'. –

Odpowiedz

5

Standard C określa trzy formy #include:

#include <file> 
#include "file" 
#include ANYTHING ELSE 

w dawnym dwóch przypadkach nie makro ekspansję ma miejsce, więc nie można zmienić zachowania. W trzecim przypadku, C99 mówi (§6.10.2p4):

The preprocessing tokens after #include in the directive are [macro-expanded]. The directive resulting after all replacements shall match one of the two previous forms [footnote: Note that adjacent string literals are not concatenated into a single string literal]. The method by which a sequence of preprocessing tokens between a < and a > preprocessing token pair or a pair of " characters is combined into a single header name preprocessing token is implementation-defined.

nieco inny, ale skutecznie równoważne sformułowanie pojawia się w C++ 98 §16.2p4.

Każde zdanie z „powinien” w nakłada twardy warunek: w tym przypadku, program jest źle sformułowane jeśli ANYTHING ELSE rozszerza się do czegokolwiek, ale sekwencji tokenów zaczynających się < a kończąc > lub rozpoczynających i kończących się na ". Dokładna interpretacja tej sekwencji tokenów to zdefiniowana implementacja, ale zauważmy, że przypis konkretnie zakazuje dosłownego konkatenacji.

Tak, jak ekspansja __FILE__ jest ciągiem stałym, jedyne sposoby, aby używać go w #include

#include __FILE__ 

które, jak odkrył, prowadzi do nieskończonej rekurencji i

#define LT < 
#define GT > 
#include LT __FILE__ etc GT 

który ma zabawne, ale bezużyteczne efekty na wszystkich kompilatorach, które mogę wygodnie przetestować. Zakładając, że powyższe jest w pliku o nazwie test.c: próby

  • GCC, aby otworzyć plik o nazwie "test.c" etc z cudzysłowów i miejsca włączone dosłownie.
  • clang jest jeszcze bardziej dosłowny i szuka tej samej nazwy pliku, ale z spacji wiodącej i końcowej.
  • MSVC makro rozszerza tylkoLT (to moja opinia uznać, że jest to naruszenie zgodności), skarży się, że nie ma dopasowania >, a następnie próbuje otworzyć plik o nazwie __FILE__ etc GT.

(GCC's behavior is documented here, jesteś na własną rękę do niczego innego.)

tl; dr: Nie ma sposobu, aby robić to, co chcesz od wewnątrz preprocesora. Polecam opracowanie nazwy pliku, który ma zostać dołączony do systemu kompilacji i powiadomienie kompilatora o przełączniku -D (w systemie Unixy potrzebna jest podwójna notacja, -DINCLUDEME='"includeme.h"'; nie mówię o CMD)

+0

system kompilacji. dzięki –

0

Najlepszym Mam wymyślić to:

#define foo(x) #x 
#include foo(x) 

prog.cpp:2:16: error: x: No such file or directory