GCC:清空结构体

4
为什么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 会生成相同的代码。

谢谢


4
如果这个结构体是联合体的一个字段,并且该联合体具有与填充重叠的其他字段,那么它会影响行为。 - Eugene Sh.
3
@EugeneSh,您是否指的是更改的填充字节?如果是的话,观察到的效果仍然相同(因为它们不应该携带任何信息)。我认为您无法保证填充字节会发生什么,而且我认为将它们清零或保持不变都是符合规范的。 - Ted Lyngmo
2
@EugeneSh。可观察行为的差异是由于未指定的行为所致。 - Ian Abbott
4
@EugeneSh. 6.2.6.1/6 可供参考。 - Ian Abbott
5
@IanAbbott 好的,我也正想发这个参考链接 :) 这是链接 http://port70.net/~nsz/c/c11/n1570.html#6.2.6.1p6 。第7段似乎也相关。 - Eugene Sh.
显示剩余17条评论
1个回答

1
在f的情况下,您隐式地将其转换为void*,因此memset()不应该对x指向的内容做出任何假设。
void * memset ( void * ptr, int value, size_t num );

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接