问题
I'm trying to create a string from multiple macros/values for use in a #include
. I'm doing this to clean up some code for an initial state in a simple state system.
I have 2 default, redefinable macros (if not defined there's a default value)
#define DEFAULT_STATE StateName // name of class
#define DEFAULT_STATE_LOCATION states/ // location of header file from root
The include directive is being used from a file 4 folders in from the root
, so the include should look like this
#include "../../../../states/StateName.h"
based on the example above.
So I want to define a macro from the 4 values.
../../../../
DEFAULT_STATE_LOCATION
DEFAULT_STATE
.h
into some macro, say DEFAULT_STATE_INCLUDE
so I can say
#include #DEFAULT_STATE_INCLUDE
(to stringize the value for quotes)
That way I can change the default state and the path from the root of the header file for the default state in a prefix header, and the source using the #include
will not have to be updated, and I can omit the constants from redefinition every time.
I'm not including the .h
in the DEFAULT_STATE
macro because I use the same macro to create and instance of the default state.
I've tried using the concatenation ##
, and the stringize operator, and some tricks I've found online, but nothing worked.
I can define ../../../../
and .h
in their own macros if needed.
But simply
#define DEFAULT_STATE_INCLUDE ../../../../ ## DEFAULT_STATE_LOCATION ## DEFAULT_STATE ## .h
#include #DEFAULT_STATE_INCLUDE
gives tons of errors.
Any help is appreciated. Thanks
回答1:
Note that footnote 143 in section §6.10.2 "Source file inclusion" of the C99 standard says:
143) Note that adjacent string literals are not concatenated into a single string literal (see the translation phases in 5.1.1.2); thus, an expansion that results in two string literals is an invalid directive.
Thus, any string concatenation must be done outside the source code. Token concatenation with ##
is not an option; that is used to build identifiers, and the bits of the header name you are joining are not identifiers.
I think you should simply use something like:
#ifndef STATE_HEADER
#define STATE_HEADER "states/StateName.h"
#endif
#include STATE_HEADER
and leave it to the build system, not the source code, to determine that -I../../../..
is required as an option to the compiler.
回答2:
You'd better pass the include directory to gcc with -I
option
-I../../../..
From gcc man page:
-I dir
Add the directory dir to the list of directories to be searched for header files.
回答3:
This seems relevant: Computed Includes
My reading of that is that the #define macro has to include the " (quote) characters and that you can't rely on the stringize or concatenation operators to do it for you.
来源:https://stackoverflow.com/questions/8782343/concatenate-and-stringize-macro-values-for-include