使用"union"在整数和数组之间键入修剪? [英] Type punning between integer and array using `union`?

查看:139
本文介绍了使用"union"在整数和数组之间键入修剪?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在整数和整数数组之间进行类型合法化是合法的吗?

Is it legal to do a type-punning between an integer and an array of integers?

特定代码:

#include <nmmintrin.h>
#include <stdint.h>

union   Uint128 {
    __uint128_t uu128;
    uint64_t    uu64[2];
};

static inline   uint_fast8_t    popcnt_u128 (__uint128_t n)
{
    const union Uint128 n_u     = {.uu128 = n};
    const uint_fast8_t  cnt_a   = _mm_popcnt_u64(n_u.uu64[0]);
    const uint_fast8_t  cnt_b   = _mm_popcnt_u64(n_u.uu64[1]);
    const uint_fast8_t  cnt     = cnt_a + cnt_b;

    return  cnt;
}

推荐答案

C11草案N1570的6.5节C节中的类型访问规则没有规定要存储structunion类型的对象可以通过除union类型的左值,包含这样的union的另一种类型的左值或字符类型的左值以外的任何其他值访问.

The type-access rules in section 6.5 paragraph C of C11 draft N1570 make no provision for an object of struct or union type to have its storage accessed by anything other than an lvalue of that union type, an lvalue of another type that contains such a union, or an lvalue of character type.

一个高质量的编译器可以看到一种类型的指针或左值被用于派生另一种类型的指针或左值,然后该类型的指针或左值被访问,该编译器应该能够识别对后者的访问,该访问是在以下情况下进行的:派生是可见的,对前者的访问.我认为该标准的作者认为它很明显可以不用说,尤其是因为即使someUnion.intMember = 3;之类的东西也会以其他方式调用UB.赋值的左操作数是类型为int的左值,没有规定允许使用类型为int的左值来访问并集类型的对象.编译器认为通过派生指针或左值进行的访问是对父级的访问的情况范围是实现质量问题;该标准未提供有关良好"实施的预期结果的指导.

A quality compiler that can see that a pointer or lvalue of one type is being used to derive a pointer or lvalue of another which is then accessed should be able to recognize that an access to the latter, made in a context where the derivation is visible, is an access to the former. I think the authors of the Standard thought that sufficiently obvious that it could go without saying, especially since even something like someUnion.intMember = 3; would invoke UB otherwise. The left-hand operand of the assignment is an lvalue of type int, and there is no provision that would allow an lvalue of type int to be used to access an object of union type. The range of situations where a compiler would recognize that an access via derived pointer or lvalue is an access to the parent is a Quality of Implementation issue; the Standard offers no guidance as to what should be expected from a "good" implementation.

对于clang和gcc所允许的内容,他们似乎认识到对someUnion.someArray[i]的访问是对联合的访问,但即使标准标准,他们也不能识别*(someUnion.someArray+i).将两个构造定义为等效.由于该标准不会要求实现就可以识别两者(甚至也不是明显的someUnion.intMember),因此,这种差异不会使clang和gcc不一致.尽管如此,应该指出的是,在基于联合识别左值时,它们是令人惊讶的盲目.

As for what clang and gcc allow, they seem to recognize that an access to someUnion.someArray[i] is an access to the union, but they do not recognize *(someUnion.someArray+i) likewise, even though the Standard defines the two constructs as equivalent. Since the Standard doesn't require that implementations recognize either (nor even the obvious someUnion.intMember), the disparity does not make clang and gcc non-conforming. Nonetheless, it should be noted that they are astonishingly blind when it comes to recognizing lvalues based on unions.

这篇关于使用"union"在整数和数组之间键入修剪?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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