[英]Include from preprocessor macro
我正在嘗試包含一個由預處理器宏構造的文件,但是由於有關令牌的規則,它似乎碰壁了。 我在這里將答案用作參考: C #include filename中的連接字符串 ,但我的情況有所不同,因為在用於構造include的定義中有小數點。 這是我目前無法通過預處理階段的內容:main.c:
#include <stdio.h>
#include <stdlib.h>
#define VERSION 1.1.0
#define STRINGIFY(arg) #arg
#define INCLUDE_HELPER(arg) STRINGIFY(other_ ##arg.h)
#define INCLUDE_THIS(arg) INCLUDE_HELPER(arg)
#include INCLUDE_THIS(VERSION)
int main(int argc, char **argv) {
printf(INCLUDE_THIS(VERSION));
fflush(stdout);
#if defined (SUCCESS)
printf("\nSUCCESS!\n");
#endif
return EXIT_SUCCESS;
}
other_1.1.0.h:
#define SUCCESS
如果我使用#define VERSION 1_1_0
並相應地重命名了標頭,它將可以工作(但我無法使用,因為我無法控制實際項目使用的標頭文件的名稱),但是1.1.0
不是有效的預處理程序令牌。
編輯:在進一步閱讀文檔后,我看到1.1.0
是有效的preprocessing number
; 導致other_1.1.0
串聯是無效的。 無論如何,仍然無法構建包含的問題。
經過一些試驗,我想出了一個雖然不理想但可行的解決方案。
#define VERSION _1.1.0
#define STRINGIFY(arg) #arg
#define INCLUDE_HELPER(arg) STRINGIFY(other ##arg.h)
#define INCLUDE_THIS(arg) INCLUDE_HELPER(arg)
#include INCLUDE_THIS(VERSION)
我不是將other_
和1.1.0
粘貼在一起,而是將other
和_1.1.0
粘貼。 我不確定為什么這是可以接受的,因為生成的令牌是相同的,但是確實存在。
我仍然希望有一個解決方案,允許我只定義版本號而不使用下划線,因此我將拒絕接受此答案,以防有人可以提出更優雅的解決方案(並為那些不願意這樣做的人使用)碰巧需要下划線)
一旦您停止考慮令牌串聯,這很容易。 字符串化可用於任何令牌序列,因此無需強制將其參數設為單個令牌。 您確實需要額外的間接調用,以便擴展參數,但這是正常的。
唯一的技巧是編寫不帶空格的序列,這就是ID
的用途:
#define STRINGIFY(arg) STRINGIFY_(arg)
#define STRINGIFY_(arg) #arg
#define ID(x) x
#define VERSION 1.1.0
#include STRINGIFY(ID(other_)VERSION.h)
有關詳細說明,請參見https://stackoverflow.com/a/32077478/1566221 。
如果您將-DVERSION=1.1.0
作為編譯行參數傳遞,而不是在源代碼中進行硬連接,那么沒有什么可以阻止您使用make
或shell進行串聯的第二個定義了。 例如,在makefile中,您可能具有:
VERSION = 1.1.0
VERSION_HEADER = other_${VERSION}.h
CFLAGS += -DVERSION=${VERSION} -DVERSION_HEADER=${VERSION_HEADER}
接着:
#include <stdio.h>
#include <stdlib.h>
#define STRINGIFY(arg) #arg
#define INCLUDE_HELPER(arg) STRINGIFY(arg)
#define INCLUDE_THIS(arg) INCLUDE_HELPER(arg)
#include INCLUDE_THIS(VERSION_HEADER)
int main(void)
{
printf("%s\n", INCLUDE_THIS(VERSION));
#if defined (SUCCESS)
printf("SUCCESS!\n");
#endif
return EXIT_SUCCESS;
}
這基本上是您的代碼,其中刪除了#define VERSION
行,並使用了VERSION_HEADER
的字符串化版本,而不是嘗試在源代碼中構造標頭名稱。 您可能要使用:
#ifndef VERSION
#define VERSION 1.1.0
#endif
#ifndef VERSION_HEADER
#define VERSION_HEADER other_1.1.0.h
#endif
對於某些合適的默認后備版本,以防運行編譯的人未在命令行上指定信息。 或者您可能使用#error You did not set -DVERSION=xyz on the command line
而不是設置默認值。
編譯時(源文件hdr59.c
):
$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -DVERSION=1.1.0 \
> -DVERSION_HEADER=other_1.1.0.h hdr59.c -o hdr59
$ ./hdr59
1.1.0
SUCCESS!
$
我會將宏的三行和#include
行放入單獨的小標題中,以便在需要版本標題時可以將其包含在內。 如果也需要默認設置,則將代碼放入單獨的標頭以供重用的重要性增加了。 該程序的源代碼可能包含:
#include "other_version.h"
並且該標頭將安排或多或少地包含正確的文件,如圖所示。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.