2009-06-21 67 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. 操作系统头

我的理由是,更具体的报头通常将包括更通用的头,并且希望通过宏修改它们。如果这些已经包括在内,那么包含警卫,或者默认宏值将会破坏系统库的行为。

的另一个理由是,这种排序阻止你“隐藏”从其他头的依赖,也就是从其他源文件包含的时候,因为他们一直有系统库本身之前包括那些标题将不会单独存在。