分配兼容的聚合类型时,字段分配的顺序是什么

时间:2018-11-02 07:09:24

标签: c

整个晚上,我一直都在寻找标准菜,没有运气。也许我想念一些东西!

在下面的代码示例中,在分配uint32_t a期间,复制到uint32_t b的副本是否与复制到*one = *two的副本相同,还是定义了此实现?

typedef struct __attribute__((packed)) {
  uint32_t a;
  uint32_t b;
} x_t;

extern x_t volatile* get_volatile_x();
extern x_t const* get_const_x();

void foo()
{
  x_t volatile* one = get_volatile_x();
  x_t const* two = get_const_x();

  *one = *two;
}

godbolt:https://godbolt.org/z/Vl0fdM

在这里和示例中,对于某些ARM标志,加载以[a,b]顺序完成,而存储以[b,a]顺序完成。

#include <stddef.h>
#include <stdint.h>

typedef struct __attribute__((packed)) {
  volatile uint32_t a;
  volatile uint32_t b;
} x_t;

extern x_t* get_x();
extern x_t volatile* get_volatile_x();
extern x_t const* get_const_x();

void foo()
{
  x_t* one = get_x();
  x_t const* two = get_const_x();

  *one = *two;
}

godbolt:https://godbolt.org/z/FcRbhm

一个有趣的事实(我对上面的C问题比这个细节更感兴趣)是该代码无法使用C ++编译器进行编译。您会收到类似以下的错误:

<source>:4:9: note: candidate function (the implicit move assignment operator) not viable: 'this' argument has type 'volatile x_t', but method is not marked volatile

因为看起来C ++期望operator=()将其视为volatile。类似https://godbolt.org/z/lt30dJ,尽管在C ++中也不是完全正确。

1 个答案:

答案 0 :(得分:3)

在分配结构时,C标准未定义结构中成员分配的顺序。

关于分配,C 2018 6.5.16.1仅说:

  

2在简单赋值std::vector)中,将右操作数的值转换为赋值表达式的类型,并替换存储在由左操作数指定的对象中的值

     

3如果从一个对象中存储的值是从另一个对象中读取的,而该对象以任何方式与第一个对象的存储重叠,则该重叠应准确无误,并且两个对象应具有兼容类型的合格或不合格版本;否则,行为是不确定的。

检查所有提及“成员”,“结构”或“结构”的标准并没有发现任何可能对作业中的成员施加按时间顺序排列的内容。 (甚至没有对结构值的明确定义;我们只能假定它实际上是其成员值的有序元组,或者也许来自“结构是由一系列序列组成的类型6.7.2.1 6中的“成员”,其值是其成员的值序列。)