我怎样才能让 C++0x 和 __STRICT_ANSI__ 相处融洽?

Posted

技术标签:

【中文标题】我怎样才能让 C++0x 和 __STRICT_ANSI__ 相处融洽?【英文标题】:How can I make C++0x and __STRICT_ANSI__ get along? 【发布时间】:2011-04-07 12:20:22 【问题描述】:

我需要在项目中使用popen,但我得到:

错误:'popen' 未在此范围内声明

看起来 GCC 在 -std=c++0x 和(与我能找到的少量信息相反)-std=gnu++0x 下定义了 __STRICT_ANSI__,这导致 popen(和 _popen)从 @987654327 中删除@。奇怪的是,取消定义 __STRICT_ANSI__ 并不能解决问题,也不能前向声明函数。我显然错过了一些东西。是否有合理的解决方法?

我使用 4.5.0 的 MinGW,并升级到 4.5.2,但仍然遇到同样的问题。我宁愿不用 msys 来编译 4.6.0,但如果必须的话,我会这样做。

【问题讨论】:

【参考方案1】:

我只是立即在命令行上取消定义它,这不是非常“干净”,但据我所知它工作正常。

-std=gnu++0x -U__STRICT_ANSI__

不应该这样做可能是有充分理由的,但它给了我想要的东西(C++0x 加上 GNU 扩展,加上遗留的东西仍然有效)。我已经这样做了很长时间,从来没有遇到过麻烦。但是如果它吃了你的猫,别怪我。

【讨论】:

什么都知道,就是这样。实际上,我在环境中的其他地方有一些相互冲突的设置,导致了恶作剧。 是的,以前去过那里...完全烦人。我发现最简单的方法是简单地将上述内容添加到 IDE 的全局编译器选项中。诚然,这不是地球上最漂亮的东西,但我从来没有因为这个问题而再次失败(无论是我自己的,也不是第三方的)。 +1 与 Cygwin 下的 gcc 4.5.3 相同。唉,__STRICT_ANSI__vsnprintf 这样的重要功能没有定义。显然,gcc 维护者并没有按照所有可能的-std=xxx 编译他们的测试套件,因为它应该是。 @AndreasSpindler:我认为这不是 GCC 问题,而是标题问题。定义 vsnprintf() 的 Cygwin 标头并非来自 GCC。 @Damon:你能展示一下如何使用这个方法吗?我想安装 ACDOtoolkit,它是一个优化包,在cmake .. 之后,然后在make 上给我这个错误(popen ...)。我尝试将您显示的标志添加到 make 命令,但它不会那样工作。如何以及在何处添加该行?【参考方案2】:

我测试了 MinGW gcc 4.6.1 和 gcc 4.7.0:它们都为-std=c++0x 定义了__STRICT_ANSI__,但没有为-std=gnu++0x 定义它。

【讨论】:

如果有人想知道,c++11gnu++11 也是如此。【参考方案3】:

问题的简短回答

如何让 C++0x 和 __STRICT_ANSI__ 相处融洽?

应该是:使用-std=gnu++0x 而不是-std=c++0x。这应该定义__STRICT_ANSI__[1],所以你可能有其他东西Makefile或构建环境仍然导致它被定义[2 ]

正如其他人所指出的那样,一个(不太受欢迎的)解决方法是使用命令行开关 -U__STRICT_ANSI__ 取消定义它。

请注意,为了指定您的代码是针对哪个 C 标准编写的,-std=gnu++* 将是使用的典型开关,而不是 -std=c++*,只要您想要 GNU 扩展(在 gcc 中,GNU 扩展默认启用,但如果您指定-std=c++*,则会禁用。

另一个注释;对于 C,这是类似的:

$ touch empty.c
$ gcc -std=c99 -E -dM empty.c | grep '\(__STRICT\|__STDC_V\)'
#define __STRICT_ANSI__ 1
#define __STDC_VERSION__ 199901L
$ gcc -std=gnu99 -E -dM empty.c | grep '\(__STRICT\|__STDC_V\)'
#define __STDC_VERSION__ 199901L

您将获得所需 C 版本的语言支持,无论是否定义了 __STRICT_ANSI__(也可能存在其他差异)。


[1]:

来自https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html

__STRICT_ANSI__

GCC 定义此宏当且仅当在调用 GCC 时指定了 -ansi 开关或指定严格符合 ISO C 或 ISO C++ 的某些版本的 -std 开关。它被定义为“1”。这个宏的存在主要是为了指导 GNU libc 的头文件将它们的定义限制在 1989 C 标准中的最小集合。

这种情况很容易得到确认(在gcc 4.8.2 上运行):

$ touch empty.cpp
$ gcc -std=c++0x -E -dM empty.cpp | grep '__STRICT'
#define __STRICT_ANSI__ 1
$ gcc -std=gnu++0x -E -dM empty.cpp | grep '__STRICT'
$ # (no match)

[2]: 可能添加了-ansi 开关?这将产生__STRICT_ANSI__,即使指定-std=gnu++*,如文档所述(参见上面的引用),并且可以很容易地检查:

$ gcc -std=gnu++0x -E -dM -ansi empty.cpp | grep '__STRICT'
#define __STRICT_ANSI__ 1

【讨论】:

以上是关于我怎样才能让 C++0x 和 __STRICT_ANSI__ 相处融洽?的主要内容,如果未能解决你的问题,请参考以下文章

我怎样才能让 QLabel 与它显示的 QPixmap 的大小完全一致?

我怎样才能访问派生类私有方法?

_stricmp with mingw 和 c++0x 不存在?

AS3 - 我怎样才能找到下载前 mp3 的总时间?

我们怎样才能找回最后一个被删除的单词

我怎样才能让这个涉及unique_ptr的代码编译?