我正在使用特定的工具链(BlackBerry Playbook NDK附带的工具链)。我认为这是基于GCC 4.4.2。当我尝试用这个工具链编译某些库时,我遇到了奇怪的问题,我认为是c ++全局命名空间的东西。例如,我会收到如下错误:
'::sprintf' has not been declared
在链接GNU c ++标准库时,我从未遇到过这些错误。但是,Playbook NDK默认使用Dinkumware C ++库,我总是要经历每个错误并且通常添加C等价物(在本例中为stdio.h)。由于我无法控制的原因,我无法链接到GNU c ++标准库,它没有出现任何这些问题。
如果我正在尝试编译更大的项目,我可以获得数百个这样的错误。有没有涉及编辑源的解决方法?在上面的例子中,文件通常包含“cstdio”作为标题,但是在'std'命名空间下声明了sprintf。所以我唯一的选择是包含C头或添加std命名空间。
答案 0 :(得分:3)
实际上,C ++标准要求在<c....>
命名空间中可以访问标准库中声明的所有符号(包括std::
标题中的C库)。它并不禁止它们也出现在全局命名空间中,并且C ++标准库的某些实现(例如libstdc ++)已经选择将它们放在那里以实现向后兼容性。
您有几种可能性:
<stdio.h>
),但通常不鼓励这样做,因为它们可能不会识别C ++并且可能会产生冲突(1)using std::printf;
using namespace std;
指令。但是你会拉很多东西...... 我的个人建议是在呼叫前加上或挑选最常用的功能,然后将它们导入全局或当前命名空间。
就迁移而言,一种直接的可能性是实际“包装”标准标题:
// cstdio.hpp
#include <cstdio>
#if defined(_DIRKUMWARE_) // note: you'll have to research the symbol to check
namespace yournamespace {
using std::printf;
using std::vptrinf;
} // namespace yournamespace
#endif // defined(_DIRKUMWARE_)
然后让脚本替换代码库中<stdio.h>
和<cstdio>
的所有匹配项<cstdio.hpp>
(显然,除此文件外)。这样,您可以针对标准库的每个实现调整此文件,而不是在包含这些函数的每个文件中重复处理。
注意(1):C标准没有规定功能是由功能还是宏提供。通常,min
和max
可能是宏。 C ++标准规定了函数,这就是使用C ++头文件通常更安全的原因。
答案 1 :(得分:2)
基本上你被困在一个角落里。
根据C ++标准:
包括
cstdio
在std
命名空间中导入符号名称,在全局命名空间中导入可能。
和
包括
stdio.h
在全局命名空间中导入符号名称,在std命名空间中导入可能。
因此,如果在包含cstdio
的特定实现中不导入全局命名空间中的符号,那么您唯一的选择是使用std
命名空间的完全限定名称。
这是因为C ++标准很好地定义了这种行为,而这种行为并不常见。
答案 2 :(得分:0)
如果源包含一些常见的头文件,您可以修改那些包含所需内容的文件。
GCC有一个名为-include
的命令行选项,允许您在编译其余文件之前强制源文件包含文件。您可以修改Makefile或项目构建脚本的等效项,以便为您执行包含。
// c_includes.h
#include <stdio.h>
#include <stdlib.h>
//...
g++ -include c_includes.h ...