什么时候关闭__STRICT_ANSI__标志是不安全的?

时间:2018-04-02 19:49:37

标签: c++ c c++11

我正在创建一个使用Apple GLKit标头的应用程序。在此库中,如果定义了__STRICT_ANSI__,它们将关闭联合。我知道如何通过编译器标志来解决这个问题,但是我不想知道为什么他们会在那里有这个,并且在什么情况下这很重要?

代码来自Apple的来源:

#if defined(__STRICT_ANSI__)
struct _GLKVector4
{
    float v[4];
} __attribute__((aligned(16)));
typedef struct _GLKVector4 GLKVector4;  
#else
union _GLKVector4
{
    struct { float x, y, z, w; };
    struct { float r, g, b, a; };
    struct { float s, t, p, q; };
    float v[4];
} __attribute__((aligned(16)));
typedef union _GLKVector4 GLKVector4;
#endif

2 个答案:

答案 0 :(得分:4)

这种保护用于使用非标准结构或特定于某些开发工具的代码。对于完全相同的问题,Microsoft标题中也存在同样的问题:无名结构/联合。

在您的特定情况下,该定义使用在C11标准之前不允许的无名结构,其中使用值__STDC_VERSION__定义标准宏201112L以指示C11支持可用。

这似乎只是旧编译器的预防措施。如果您尝试使用前C11进行编译,则会出现错误。

正确的定义应该是:

#if defined(__STDC_VERSION__) && (__STDC_VERSION__ < 201112L)

请注意__STDC_VERSION__小于201112L的比较,假设新标准将继续支持无名结构/联合。

无论如何,在我们没有正确识别它们的原因时,必须始终在删除条件编辑之前采取一些谨慎措施。

答案 1 :(得分:3)

我认为他们滥用了__STRICT_ANSI__宏。它没有被任何标准定义,而只是由GCC和兼容的编译器来表示您使用-std=c99 / -std=c11 / etc。在这种情况下,默认情况下系统头不应该污染命名空间C标准不允许的任何内容。

如果图书馆以某种hackish方式使用联盟,但实际上并不是有效的C(例如有未定义的行为)但是GCC允许这样做,他们不应该使用#ifndef __STRICT_ANSI__而是使用#ifdef __GNUC__

在任何情况下,很难确定在没有看到实际代码的情况下告诉你什么,但我很确定你可以忽略它。