2014-10-27 64 views
1

我想知道我是否可以依靠標準報頭中包含守衛的特定定義。如果我用Visual Studio查看我的系統,例如,我可以看到stdint.h定義了_STDINT。我的問題是,如果我也可以依靠#define來編譯其他編譯器。基本上,我這樣做是安全的這樣做:我可以依靠標準報頭中的包含守衛

#ifndef _STDINT 
typedef char int8_t; 
#endif 

我知道這可能看起來很愚蠢。爲什麼不只是包含stdint.h你說?那麼我正在編寫可能部署嵌入式目標的代碼,這可能並不滿足於包含某些標準c頭文件。但是,我希望能夠在可用時使用它們。因此,我希望能夠在具有int main()的文件中選擇是否要包含stdint.h。

+8

簡短的答案是否定的,長的答覆是親愛的神 - 不要 - 做這個。下劃線#define僅爲文件範圍保留,因此在該文件之外使用它們是充滿風險的。 處理這個(imho)的正確方法是提供你自己的「stdint.h」,如果它在目標機器上找不到的話。我會做一個可選的包含目錄,如果編譯器不兼容c99/posix,則包含該目錄。然後用'#include「stdint.h」'包含stdint。 – IdeaHat 2014-10-27 14:29:24

+0

「一個可選的包含目錄,如果編譯器不兼容c99/posix,則包含該目錄」。原諒我的無知。我怎麼做?通過編譯器標誌?或者根據c99配置我的系統的另一個頭文件定義了什麼? – xaviersjs 2014-10-27 14:32:55

+0

@xaviersjs它依賴於編譯器,但是,它通常歸結爲給編譯器一條額外的路徑。 – user694733 2014-10-27 14:36:14

回答

0

您可以依賴標準庫頭來聲明(而不是超過)指定要聲明的內容。這意味着:

  • 如果一個功能是可選的,該標準將指定一個功能測試宏,你可以檢查與#if#ifdef,告訴你,如果它是您的平臺上。例如threads.h在C11中是可選的,因此標準規定__STDC_NO_THREADS__被定義爲1,如果標頭不可用。

  • 如果一個功能不是可選的,你應該能夠假定它存在!如果它不存在,編譯器不符合語言版本,並且您最好希望這些東西在文檔中明確說明,因爲您已進入實現定義的範圍。

  • 許多功能都是作爲宏提供的,或者提供了相關的宏定義;因此您可以測試獨立於整個標題的這些特徵的存在。

所以對於stdint.h的情況下,也沒有提供,因爲頭是不可選的功能測試宏。如果它不存在,編譯器應該記錄下來,而不是聲稱符合標準。但是,stdint.h中的某些功能是可選的,因此可以使用它們的關聯宏單獨進行測試。

例如,在7.20中描述(int8_t等)的準確寬度整數類型需要相關的描述他們的最大值和最小值的宏定義(並且這些宏特別不如果類型不可用定義) ,因此您可以通過測試INT8_MAX是否在包含標頭後定義來測試int8_t的特定可用性。

1

不幸的是:)。這就是爲什麼像autoconf這樣的東西和朋友存在的原因,以便能夠實際編譯小程序並提前測試以確定系統是否包含特定的符號和標題;無法通過單程編輯您的程序來完成。

這裏的例子中,「Visual Studio stdint.h」實際上並不存在於較舊的Visual Studio版本中。

如上所述,正確的解決方案是使用某種源外配置系統來確定要執行的操作。

有時候,你也許能夠擺脫簡單的東西,取決於你從stdint.h一個子集有多大用:

  • 使用項目前綴的固定類型(my_I32爲例),並定義他們爲int;如果事先知道所有目標平臺將具有int作爲32位整數。

  • 使用項目提供的stdint.h並將此文件的路徑放在預處理器搜索路徑中。請注意,這需要您的項目以及此項目的任何依賴關係(包括系統標題)僅使用此文件中定義的聲明的子集。