更具體地說,是否可以在編譯時檢測是否包含 C 標準頭檔案(比如說<complex>),并以跨平臺和跨編譯器的方式進行檢測?我希望它至少可以與 C 11 一起使用,但就問題而言,任何 C 標準都可能嗎?
我知道 C 標準庫的實作依賴于編譯器和作業系統,但是是否有標頭的標準化保護名稱,我可以檢查是否存在的宏?
我遇到了這個:檢測 C 中 STL 的使用,這是不使用標頭的一種技巧,并且:有沒有一種方法可以便攜地檢測使用宏包含標準標頭?,它以 C 17 特性回答,實際上更多的是關于檢測函式。
我想要的是能夠在代碼中的給定點撰寫一些前處理器指令,以判斷是否包含標頭(還)。我檢查了(的實作)的源代碼<complex>作為示例,并_GLIBCXX_COMPLEX定義了,但可能僅用于此實作。
uj5u.com熱心網友回復:
TL;DR:不,除了 C 17 特性之外沒有#if __has_include(<complex>)。無論如何都沒有定義宏。
長答案:答案分為兩部分。我從一些標題中讀到的內容,以及我在不同作業系統上使用不同編譯器運行的測驗。
警告:我也會寫關于 C 的文章,因為一些編譯器使用相同的宏。我還使用快捷方式“for C”和“for C ”而不是“當complex.h包含標題時”和“當包含標題時<complex>”。
好的,這是我目前最好的答案。
關于 C 和complex.h:
在 C 中,宏的存在
_Complex_I是我認為應該在任何complex.h標題中定義的唯一宏,因為它由 ISO C99 指定(參見 ISO/IEC 9899:1999/TC3 文本)。我進行的測驗表明這是一個現實的假設。使用了一些附加宏,例如在使用 GCC編譯和使用 MSVC 編譯_COMPLEX_H時似乎已定義。_C_COMPLEX_T可能還有其他的,我沒有找到,請不要猶豫添加它們。
但它是 C,而不是 C ,不應將兩者混用。
關于 C 和<complex>:
C 標準 (ISO/CEI 14882:2011) 沒有指定這樣的宏。事實上,它沒有指定包含任何宏(乍一看)。但是,它確實指定了complex該類的存在,但這并不能回答問題。對于我閱讀的內容,_COMPLEX_似乎 _C_COMPLEX_T是在<complex>LLVM-clang 和 MSVC 的標頭中定義的,而且在complex.hC 數學庫 (libm) 的蘋果實作中也有定義。
但是,我在 macOS 上使用 LLVM-clang 編譯器進行的測驗未能顯示這些宏,并且我找不到讀取該資訊的檔案。我還發現 g 正在定義_GLIBCXX_COMPLEX.
如果想用早于 C 17 的 C 來實作這一點,一種解決方案是使用代碼將運行的給定編譯器和架構進行測驗。這很糟糕,但這是我得到的最接近的答案。
測驗:
我在這里給出了我在不同作業系統上運行的代碼、編譯器選項、它們的版本以及它們提示的結果。_Complex_I確實是為所有 C 頭檔案定義的。
我無法使用 GCC 和 G 在 macOS 上運行測驗,但我敢打賭,_Complex_I它將使用 GCC 和_GLIBCXX_COMPLEXG 來定義。
C 測驗
G -std=c 11 v9.3.0 在 Ubuntu 20.04 上:
_GLIBCXX_COMPLEX
Windows 10 上的 G -std=c 11 v11.2.0(通過 Cygwin):
_GLIBCXX_COMPLEX
Windows 10 上的 MSVC 默認 c 11 選項 v14.29.xxxxx.x:
_C_COMPLEX_T
_COMPLEX_
Apple LLVM-clang -std=c 11 v10.0.1 : None(不代表沒有,只是不知道是哪一個)
C 代碼:
#include <iostream>
#include <complex>
int main(){
#ifdef _COMPLEX_
std::cout << "_COMPLEX_" << std::endl;
#endif
#ifdef _C_COMPLEX_T
std::cout << "_C_COMPLEX_T" << std::endl;
#endif
#ifdef _COMPLEX_H
std::cout << "_COMPLEX_H" << std::endl;
#endif
#ifdef _Complex_I
std::cout << "_Complex_I" << std::endl;
#endif
#ifdef _GLIBCXX_COMPLEX
std::cout << "_GLIBCXX_COMPLEX" << std::endl;
#endif
return 0;
}
測驗 C :
GCC -std=c99 v9.3.0 on Ubuntu 20.04 :
_Complex_I _COMPLEX_H
GCC -std=c99 v11.2.0 on windows 10 (via Cygwin) :
_Complex_I _COMPLEX_H
MSVC -std=c99 v14.29.xxxxx.x on windows 10 :
_Complex_I _C_COMPLEX_T
Apple LLVM-clang -std=c99 v10.0.1 : _Complex_I
Code for C:
#include <stdlib.h>
#include <stdio.h>
#include <complex.h>
int main(){
#ifdef _COMPLEX_
printf("_COMPLEX_\n");
#endif
#ifdef _C_COMPLEX_T
printf("_C_COMPLEX_T\n");
#endif
#ifdef _COMPLEX_H
printf("_COMPLEX_H\n");
#endif
#ifdef _Complex_I
printf("_Complex_I\n");
#endif
#ifdef _GLIBCXX_COMPLEX
printf("_GLIBCXX_COMPLEX\n");
#endif
return 0;
}
To sum up :
MSVC is defining _C_COMPLEX_T whatever C or C used, and also _COMPLEX_ for C . _Complex_I is always defined for C, and G seems to define _GLIBCXX_COMPLEX whatever the plateform (test to be done on macOS) for C .
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/425960.html
