初始化结构与匿名结构有什么区别?

时间:2019-07-28 01:19:43

标签: c gcc optimization struct union

考虑以下代码:

typedef struct {
  uint32_t a : 1;
  uint32_t b : 1;
  uint32_t c : 30;
} Foo1;

void Fun1(void) {
  volatile Foo1 foo = (Foo1) {.a = 1, .b = 1, .c = 1};
}

在嵌入式应用程序中使用位字段对寄存器进行打孔时,此常规模式会出现很多。使用带有-O3-std=c11的最新ARM gcc编译器(例如gcc 8.2或gcc 7.3),我得到以下程序集:

  sub sp, sp, #8
  movs r3, #7
  str r3, [sp, #4]
  add sp, sp, #8
  bx lr

这几乎就是您想要和期望的。 Foo不是易失性的,因此在将最终存储到易失性变量(寄存器)0x7之前,可以将每个位的初始化组合在一起,成为文字foo

但是,能够操纵整个寄存器的原始内容很方便,这会导致位字段的匿名实现:

typedef union {
  struct {
    uint32_t a : 1;
    uint32_t b : 1;
    uint32_t c : 30;
  };
  uint32_t raw;
} Foo2;

void Fun2(void) {
  volatile Foo2 foo = (Foo2) {.a = 1, .b = 1, .c = 1};
}

不幸的是,生成的程序集并未如此优化:

  sub sp, sp, #8
  ldr r3, [sp, #4]
  orr r3, r3, #1
  str r3, [sp, #4]
  ldr r3, [sp, #4]
  orr r3, r3, #2
  str r3, [sp, #4]
  ldr r3, [sp, #4]
  and r3, r3, #7
  orr r3, r3, #4
  str r3, [sp, #4]
  add sp, sp, #8
  bx lr

对于密集封装的寄存器,每位的读-修改-写操作可能会变得...昂贵。

union /匿名结构有什么特别之处,它阻止了gcc像纯结构一样优化初始化?

0 个答案:

没有答案