【发布时间】:2013-12-19 00:57:57
【问题描述】:
考虑相同代码的两个略有不同的版本:
struct s
{
int dummy[1];
};
volatile struct s s;
int main(void)
{
s;
return 0;
}
和
struct s
{
int dummy[16];
};
volatile struct s s;
int main(void)
{
s;
return 0;
}
这是我为他们使用 gcc 4.6.2 的结果:
_main:
pushl %ebp
movl %esp, %ebp
andl $-16, %esp
call ___main
movl _s, %eax
xorl %eax, %eax
leave
ret
.comm _s, 4, 2
和
_main:
pushl %ebp
movl %esp, %ebp
andl $-16, %esp
call ___main
xorl %eax, %eax
leave
ret
.comm _s, 64, 5
请注意在第二种情况下无法访问s。
这是编译器的错误,还是我只是在处理 C 标准的以下声明,而 gcc 开发人员只是选择了这种奇怪的实现定义并仍在按规则行事?:
什么构成对具有 volatile 限定类型的对象的访问是实现定义的。
造成这种差异的原因是什么?我自然希望整个结构都被访问(或者不被访问,我不确定),不管它的大小和里面有什么。
附:在这种情况下,您的编译器(非 gcc 或更新的 gcc)会做什么? (如果这是您要解决的唯一部分,请在评论中回答最后一个问题,因为这不是要问的主要问题,而是更多好奇的问题)。
【问题讨论】:
-
我刚刚尝试使用 GCC 4.8.0,它的效果类似:1 字版本仍然可以单读,但 16 字版本没有。但是,如果我说“s=s”,即使是 16 条目的结构也会得到一个副本。
-
这很有趣:GCC 4.6.0 手册专门调用了 scalar volatiles,而 GCC 4.0.4 手册没有(我碰巧用 google 很快找到了两个) . 4.6.0:gcc.gnu.org/onlinedocs/gcc-4.6.0/gcc/Volatiles.html 4.0.4:gcc.gnu.org/onlinedocs/gcc-4.0.4/gcc/Volatiles.html 在您的示例中,具有单个 int 的结构是“标量”,而具有 16 个 int 的结构不是。
-
@JoeZ 我没有访问结构内部的标量,而是访问整个结构(或者我认为是这样)。
-
对,但我相信 GCC 会将适合寄存器的结构转换为标量访问。 IE。
struct { int x[1]; }在许多情况下被视为标量。我不认为这是有保证的,请注意,如果你问我,它似乎是一个实现工件。也许你应该在 GCC 开发者名单上问一下? -
这可以是related吗?