除了在C严格别名规则6.5.2.3从结构和工会会员 [英] Exception to strict aliasing rule in C from 6.5.2.3 Structure and union members

查看:181
本文介绍了除了在C严格别名规则6.5.2.3从结构和工会会员的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

从C99标准报价:

6.5.2.3

5的一个特别保障是为了简化使用工会提出:如果一个工会包含共享一个公共初始序列几种结构(见下文),如果联合对象当前包含这些结构之一​​,它允许检查任何它们的共同起始部分的任何地方完整的类型工会的声明是可见的。两个结构共享一个通用初始序列如果对应成员有兼容的类型(并且对于比特字段,相同的宽度)为一个或多个初始成员的序列

5 One special guarantee is made in order to simplify the use of unions: if a union contains several structures that share a common initial sequence (see below), and if the union object currently contains one of these structures, it is permitted to inspect the common initial part of any of them anywhere that a declaration of the complete type of the union is visible. Two structures share a common initial sequence if corresponding members have compatible types (and, for bit-fields, the same widths) for a sequence of one or more initial members.

有例子是这种情况:

// The following code is not a valid fragment because
// the union type is not visible within the function f.

struct t1 { int m; };
struct t2 { int m; };

int f(struct t1 *p1, struct t2 *p2)
{
    if (p1->m < 0)
        p2->m = -p2->m;
    return p1->m;
}

int g()
{
    union
    {
        struct t1 s1;
        struct t2 s2;
    } u;

    /* ... */
    return f(&u.s1, &u.s2);
}

我添加了一些变化:

I have added few changes:

#include <stdio.h>

struct t1 { int m; };
struct t2 { int m; };

union u
{
    struct t1 s1;
    struct t2 s2;
};

int foo(struct t1 *p1, struct t2 *p2)
{
    if (p1->m)
        p2->m = 2;
    return p1->m;
}

int main(void)
{
    union u u;
    u.s1.m = 1;
    printf("%d\n", foo(&u.s1, &u.s2));
}

正如你可以看到我已经搬到联合声明外,使它将成为富可见()。据标准的评论,这应该让我的code正确的,但它看起来像严格别名仍然打破这个code为3.4铿锵和gcc 4.8.2。

As you can see I have moved union declaration outside so it would be visible in foo(). According to the comment from standard, this should have made my code correct but it looks like strict aliasing still breaks this code for clang 3.4 and gcc 4.8.2.

用-O0输出:

2

与-O2输出:

1

为编译器。

所以我的问题是:

为C真正依靠工会的声明,以决定是否一些结构异常严格别名规则?或者两者的gcc /铛有错误吗?

is C really relies on union declaration to decide if some structures are exception to strict aliasing rule? Or both gcc/clang have a bug?

看来真的打破我的,因为即使功能和工会都在同一个标​​题声明,这并不能保证工会在翻译单元可见与功能的机构。

It seems really broken to me, because even if function and union are both declared in the same header, this does not guarantee that the union is visible in translation unit with body of the function.

推荐答案

最重要的一点是,你的变化(移动联合起来​​)不改变函数的定义可言。它仍然是接收无关指针的函数。在你的榜样,而在其他地方,这可能是不同的传递指针有关。编译器的目标是服务于最一般的情况。该函数的身体后变不同,目前尚不清楚为什么。

The most important point is that your change (moving the union up) is not changing the definition of the function foo at all. It is still a function that receives unrelated pointers. In your example the passed pointers are related while elsewhere this might be different. The goal of compiler is to serve the most general case. The body of the function is different after the change and it is not clear why.

这是你问的问题是关于优化如何小心在特定的命令行键的特定的编译器实现的。它无关的存储器布局。在一个正确的编译器的结果应该是相同的。编译器应该处理的情况下,当2个不同的指针实际上指向内存中的同一个地方。

The question that you are asking is about how careful optimization is implemented in your particular compiler for certain command line keys. It has nothing to do with the memory layout. In a correct compiler the result should be the same. Compiler should handle the case when 2 different pointers in fact point to the same place in memory.

这篇关于除了在C严格别名规则6.5.2.3从结构和工会会员的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆