联合类型的数组是否可以强制转换为活动类型的指针?

时间:2017-10-04 17:14:18

标签: c++ arrays pointers unions

给定一些union类型的数组,如果满足以下条件:

  • 数组中每个union的活动成员都是相同的,
  • sizeof union中的每个成员都是相同的,
  • alignof union中的每个成员都是相同的
  • (可能)联盟满足StandardLayoutType
  • 的要求

然后是安全的以下行动:

  1. 将此数组转换为活动类型的指针(用于将其作为活动类型的数组进行寻址)
  2. 解决除上述数组的第一个元素以外的任何内容?
  3. 假设1& 2是可能的;这适用于非标准布局类型吗?
  4. 例如,请考虑以下代码段:

    template<typename T, typename U>
    union storage_type
    {
        T value0;
        U value1;
    };
    
    static_assert( sizeof(int) == sizeof(float), "" );
    static_assert( alignof(int) == alignof(float), "" );
    
    storage_type<int,float> storage[] = { {1}, {2}, {3} };
    
    // the active type of all storage_type is 'int', so cast to int*
    // to be treated as an array of ints
    
    auto* array = reinterpret_cast<int*>(&storage[0]);
    
    assert( array[0] == 1 );
    assert( array[1] == 2 );
    assert( array[2] == 3 );
    

    我对C ++标准明确说明这种情况感兴趣。我知道StandardLayoutType可以安全地投射到结构的第一个成员或联盟的活跃元素,所以我怀疑我的第一个演员是安全的;但我不确定这是否适用于数组,并将其视为活动类型的数组。

    我尝试在SO和C ++标准(N4660 C ++ 17草案)中进行一些搜索 - 但我没有运气

    注意:由于编译器具有C兼容性,此问题与在实践中是否有效无关;这是否是在C ++中调用UB以及它是否违反严格别名规则的问题。

1 个答案:

答案 0 :(得分:0)

理论上讲,这可能会失败。按照标准:

  

联合的大小足以包含其最大的数据成员。

因此,从理论上讲,sizeof(my_union)和sizeof(largest_member)可能会有所不同。

如果你static_assert()它是相同的,那么:

int* array = &storage[0].value0;

...由于数组索引的工作原理,它是否可以无UB。