各位,
考虑一下这段(令人讨厌的)代码:
volatile unsigned long a[1];
unsigned long T;
void main(void)
{
a[0] = 0x6675636b; /* first access of a */
T = *a;
*(((char *)a) + 3) = 0x64; /* second access of a */
T = *a;
}...the问题:((char *)a)是易挥发的还是非易失性的?
这就引出了一个更大的问题:两个访问之间是否应该存在依赖关系?也就是说,人类的常识说有,但是C99标准说易挥发的东西不会别名非易失性的东西--所以如果((char *)a)是非易失性的,那么这两个访问就没有别名,也没有依赖性。
更准确地说,C99 6.7.3 (第5段)内容如下:
“如果试图通过使用具有非易失性限定类型的lvalue来引用使用易失性限定类型定义的对象,则该行为是未定义的。”
那么,当我们键入a时,是否适用易失性限定符?
发布于 2012-11-07 17:55:41
当有疑问时,运行一些代码:)我创建了一些类似的(稍微不那么可恶的)测试代码( msvs 2K10中的win32 C++应用程序)。
int _tmain(int argc, _TCHAR* argv[]) {
int a = 0;
volatile int b = 0;
a = 1; //breakpoint 1
b = 2; //breakpoint 2
*(int *) &b = 0; //breakpoint 3
*(volatile int *) &b = 0; //breakpoint 4
return 0;
}在编译以供发布时,允许我在2和4处断点,但不允许1和3断点。
我的结论是,类型决定了行为,1和3被优化。直觉支持这一点--否则编译器必须保留某种类型的列表,将所有内存位置列为易失性的,并检查每次访问(硬的、难看的),而不仅仅是将其与标识符的类型相关联(更容易、更直观)。
我还怀疑它是特定于编译器的(甚至在编译器中也可能是特定的),并且会在任何平台上进行测试,然后根据这种行为进行测试。
实际上,我只是尝试不依赖于这种行为:)
而且,我知道你是专门问数组的,但我怀疑这会有什么区别。您可以轻松地为数组编写类似的测试代码。
发布于 2012-11-02 16:42:33
就像你说的,它的“未定义”。这意味着恶魔会从你鼻子里冒出来。请尽量坚持“定义”的行为。volatile说明符将要求编译器不要优化该值,因为它是一个“重要”和临界值,如果由于不同的优化机制而更改,可能会导致问题。但这是它所能做的。
https://stackoverflow.com/questions/13199364
复制相似问题