【发布时间】:2016-07-31 14:20:03
【问题描述】:
假设我定义了一个unsigned char foo;,标准保证它没有陷阱表示。根据this answer,在获取地址之前访问它仍然是未定义的行为。这是来自 N1570,“6.3.2.1 左值、数组和函数指示符”第 2 段的参考:
如果左值指定一个自动存储持续时间的对象, 可以用寄存器存储类声明(从来没有 它的地址被占用),并且该对象未初始化(未声明 使用初始化程序并且之前没有对其进行分配 使用),行为未定义。
但是,我想知道volatile unsigned char foo; 是否会调用未定义的行为?将 volatile 限定的变量存储在寄存器中似乎是不可能的。
另外,下面的代码定义好了吗?
unsigned char foo;
*&foo -= *&foo;
这个问题来自第102个脚注:
102) ...... *&E 是函数指示符或等于 E 的左值。......
【问题讨论】:
-
w.r.t
volatile、register和“存储在寄存器中”在 C 中是完全不相关的概念,其中一个并不意味着另一个。 6.7.3:“具有 volatile 限定类型的对象可能会以实现未知的方式进行修改.. 构成对具有 volatile 限定类型的对象的访问是实现定义的。”即volatile的意义在于超越标准定义的行为。 -
“在地址被占用之前访问它” - 你从哪里得到的?除非使用了变量的地址(例如,应用了
&运算符),否则变量甚至不需要有地址。而*&与不应用它们中的任何一个相同,请阅读整个脚注 102。 -
@Olaf 但是标准只是写了“......可以用寄存器存储类声明(从未使用过它的地址),......”,并且使用的地址是不需要
-
register只是防止地址被占用,因此您不能对其应用&。拥有auto volatile register变量没有任何意义。这不能在外部进行更改(没有链接等),如果编译器可以证明它没有效果,编译器甚至可能会对其进行优化(为什么使用此类代码的延迟循环在非常激进的编译器上可能会出现问题)。其实光靠auto volatile已经很没用了。 -
@Olaf 你的意思是
auto volatile register限定符/说明符几乎等同于volatile,唯一的区别是不能取定义的变量的地址?
标签: c language-lawyer undefined-behavior c11