2009-06-21 57 views
3

我需要使用系統特定的功能,例如ftello()(根據POSIX標準在stdio.h中定義)。我還需要使用標準的C++特性,例如std::sprintf()(根據ISO C++標準在cstdio中定義)。包括<cstdio>和<stdio.h>的正確順序?

據我所知,只包括<cstdio>不保證定義非標準C++的東西,所以我想我必須包括。 我很久以前就讀過(例如)使用gcc時,包含文件順序可能存在問題。

那麼,什麼是既包括<cstdio><stdio.h>正確的順序? 我正在尋找一個儘可能跨平臺的解決方案(至少對於gcc,suncc,intel C++/linux和mingw)。

回答

2

OK,經過一番更reasearch我終於來到了,首先,包括C++頭一個結論,C頭後面是做正確的事。 例如,考慮下面的C++ 0x頭(來自GCC):

/usr/include/c++/4.3/tr1_impl/cstdint:


// ... 
#define __STDC_LIMIT_MACROS 
#define __STDC_CONSTANT_MACROS 
#include_next <stdint.h> 
// ... 

它的作用是,它定義了兩個C99宏,然後才包含C99 stdint.h頭文件。原因是在C99中,stdint.h的一些功能是可選的,並且只有在定義了這些宏時纔可用。但是,在C++ 0x中,所有stdint.h功能都是必需的。現在 ,如果我第一次包括了C99 stdint.h,cstdint後來,我不會因爲在stdint.h頭守衛的強制性的C++ 0x功能。 有人可能會爭辯說這是編譯器廠商的錯,但那是不正確的。 stdint.h是一個系統綁定的頭文件(在本例中爲glibc),它是一個C99頭文件,並且不知道任何關於C++ 0x(它畢竟可以是舊系統)或gcc。編譯器無法真正修復所有的系統頭文件(在這種情況下,總是在C++模式下啓用這些功能),但它必須在這些系統上提供C++ 0x支持,因此供應商使用此替代方法。

2

對於系統頭文件,包含的順序通常不應該是錯誤的來源。

對於其他頭文件請看similar question here at SO

+0

感謝您的回答。 我想我發現了一個類似的問題在這裏: http://gcc.gnu.org/ml/libstdc++/2003-01/msg00210.html 我居然通過它絆倒了前一段時間,但我不記得細節。標題肯定是通過系統。 雖然這是一個系統/編譯器的問題,我問的是,也許有人知道對付這種東西的嘗試方法。 – Alex 2009-06-21 16:23:16

0

從我所知道的,ftello()和sprintf()都包含在stdio.h中。

包括訂單可非標頭無所謂,你必須檢查的依賴結構,找出哪些是依賴於其他,並將其包含在正確的順序。

爲此,相關性包括文件應包含在包含文件中,而不是依靠「用戶」,以確保它們正確包括在內。

+0

是,ftello()和sprintf()是stdio.h中,但我在談論的std :: sprintf的(),這可能是也可能不是一樣的sprintf()。實際上,它可能不是,因爲sprintf()通常是一個編譯器定義的宏,而std :: sprintf()保證是一個函數(你可以把它作爲地址)。 所以,我需要從cstdio使用ftello()stdio.h中和std :: sprintf的()。 兩者都是從標準包括文件,但由於這兩個文件有特殊關係,我不知道它是在不同的編譯器/操作系統組合可靠地工作正確的順序。 – Alex 2009-06-21 17:57:05

2

我不知道任何真正的規則,但是一般來說,我將更低級別的系統庫包含在更高級別的庫之前。

因此,在這種情況下,stdio.h是一個C標頭,並且(在我的想象中)更接近機器,並且<cstdio>是更高級別的C++標準庫,我認爲它更爲抽象。

我自己傾向於在cstdio之前包括stdio.h,但我不知道支持該理由的確切原因。

0

你擔心沒有理由。 <cstdio>的內容是「似乎通過包含」<stdio.h>(17.4.1.2標題/ 4)的內容。不過,聲明和定義(但不是宏)的名稱空間是std。

所以,你可能需要寫std::ftello()。爲了提高便攜性,請投入using std::ftello;,您無需關心。

+0

ftello()不在C++標準中,std命名空間中沒有ftello()(至少在gcc的libstdC++中)。 無論如何,謝謝! – Alex 2009-06-23 13:50:41

+0

這正是我的觀點。 C++標準沒有詳細說明stdio.h中的內容。它只是說cstdio包含stdio.h中的任何內容,但是在命名空間std中。如果libstdC++將ftello放入stdio.h中但不放入cstdio中,則違反了17.4.1.2。 – MSalters 2009-06-24 08:26:03

0

我把最具體的東西在上面,並在底部的最具體的東西。對於例如源文件時,它應該是這樣的:

  1. 預編譯的頭,如果有的話
  2. 頭這個源文件
  3. 項目包括
  4. 大多數特定的庫,在這種情況下庫項目,或公司的庫
  5. 最不具體的庫,如像升壓 「系統」 文庫,或SDL
  6. 標準C++
  7. 標準C
  8. 操作系統頭

我的理由是,更具體的報頭通常將包括更通用的頭,並且希望通過宏修改它們。如果這些已經包括在內,那麼包含警衛,或者默認宏值將會破壞系統庫的行爲。

的另一個理由是,這種排序阻止你「隱藏」從其他頭的依賴,也就是從其他源文件包含的時候,因爲他們一直有系統庫本身之前包括那些標題將不會單獨存在。

相關問題