通过工会别名 [英] Aliasing through unions

查看:33
本文介绍了通过工会别名的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

6.5(p7) 有一个关于 unions 和 aggregates 的项目符号:

The 6.5(p7) has a bullet about unions and aggregates:

一个对象的存储值只能由左值访问具有以下类型之一的表达式:

An object shall have its stored value accessed only by an lvalue expression that has one of the following types:

[...]

——一个聚合或联合类型,包括上述之一其成员之间的类型(包括递归地,子聚合或包含联合),或

— an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union), or

这不是很清楚它的意思.是否需要至少一个成员所有成员来满足严格的别名规则.特别是关于 unions:

This is not quite clear what it means. Does it require at least one member or all members to satisfy the strict aliasing rule. Particularly about unions:

union aliased{
    unsigned char uint64_repr[sizeof(uint64_t)];
    uint64_t value;
};

int main(int args, const char *argv[]){
    uint64_t some_random_value = 123;
    union aliased alias;
    memcpy(&(alias.uint64_repr), &some_random_value, sizeof(uint64_t));
    printf("Value = %" PRIu64 "\n", alias.value);
}

演示

程序的行为是否明确定义?如果不是,项目符号是什么意思?

Is the behavior of the program well-defined? If no, what does the bullet mean?

推荐答案

使用 union 意味着什么是避免类型双关和严格别名违规的标准兼容方法之一如果您试图通过不同类型的指针访问存储的值,就会发生这种情况.

What is means is using a union is one of the standard compliant ways to avoid type punning and the strict aliasing violation that would otherwise occur if you attempted to access a stored value through a pointer of a different type.

unsignedfloat 为例,通常都是 32 位,在某些情况下从 unsigned* 或可能需要 float*.例如,您不能这样做:

Take for example unsigned and float, generally both 32-bits and in certain cases looking at the stored value from either unsigned* or float* may be needed. You cannot for example do:

    float f = 3.3;
    // unsigned u = *(unsigned *)&f;  /* violation */

遵循 6.5(p7),您可以使用两种类型之间的 union 并访问与 unsignedfloat 相同的信息,而无需对指针进行类型双关或违反严格的别名规则,例如

Following 6.5(p7) you can use a union between both types and access the same information as either unsigned or float without type-punning a pointer or running afoul of the strict aliasing rule, e.g.

typedef union {
    float f;
    unsigned u;
} f2u;
...    
    float f = 3.3;
    // unsigned u = *(unsigned *)&f;  /* violation */
    f2u fu = { .f = f };
    unsigned u = fu.u;                /* OK - no violation */

所以严格的别名规则防止通过另一种类型的指针访问具有有效类型的内存,除非该指针是 char 类型或指向两种类型之间联合成员的指针.

So the strict aliasing rule prevents accessing memory with an effective-type through a pointer of another type, unless that pointer is char type or a pointer to a member of a union between the two types.

(注意:该标准的这一部分绝不是一个清晰的例子.(你可以阅读 10 遍,仍然挠头)它的目的是遏制滥用指针类型,同时仍然认识到任何形式的内存块都必须能够通过字符类型访问,(union 是其他允许的访问方式之一).

(note: that section of the standard is one that is anything but an example of clarity. (you can read it 10 times and still scratch your head) Its intent is to curb the abuse of pointer types, while still recognizing that a block of memory in any form must be capable of being accessed through a character type, (and a union is among the other allowable manners of access).)

过去几年,编译器在标记违规行为方面做得更好.

Compilers have gotten much better in the past few years at flagging violations of the rule.

这篇关于通过工会别名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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