【问题标题】:GCC: Zeroing a structGCC:归零结构
【发布时间】:2021-09-18 04:39:46
【问题描述】:

为什么 gcc 会为以下函数创建不同的汇编代码以将结构清零?

typedef struct {
    char a;
    int b;
} A;

void f(A *x) {
    memset(x, 0, sizeof(*x));
}

void g(A *x) {
    x->a = 0;
    x->b = 0;
}

void h(A *x) {
    *x = (A) {0};
}

大会 (-Ofast):

f:
        mov     QWORD PTR [rdi], 0
        ret
g:
        mov     BYTE PTR [rdi], 0
        mov     DWORD PTR [rdi+4], 0
        ret
h:
        mov     QWORD PTR [rdi], 0
        ret

我认为这是因为数据结构的填充,但是 gcc 是否不允许覆盖填充字节,因为它们无论如何都不能使用?我实际上希望fgh 产生相同的代码。

谢谢

【问题讨论】:

  • 事实上,如果这个结构是联合的一个字段,它的附加字段与填充重叠,它会在行为上有所不同。
  • @EugeneSh。您指的是更改后的填充字节吗?如果是这样,可观察到的效果仍然是相同的(因为它们不应该携带任何信息)。我认为您无法保证填充字节会发生什么,我认为将它们归零和保持不变都是符合要求的。
  • @EugeneSh。可观察行为的差异是由于未指定的行为。
  • @EugeneSh。 6.2.6.1/6 供参考。
  • @IanAbbott 是的,也正要发布这个参考:)这里是链接port70.net/~nsz/c/c11/n1570.html#6.2.6.1p6。 p7 似乎也很相关

标签: c gcc language-lawyer padding memset


【解决方案1】:

在 f 的情况下,您隐式转换为 void*,因此 memset() 不应假设 x 指向的内容。

void * memset ( void * ptr, int value, size_t num );

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-02-02
    • 1970-01-01
    • 2015-09-16
    • 2015-08-16
    • 2015-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多