Concatenate and stringize macro values for #include

旧街凉风 提交于 2021-02-17 06:22:07

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!