赋值表达式中的Volatiles [英] Volatiles in assignment expressions

查看:69
本文介绍了赋值表达式中的Volatiles的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

嗨!


我试着将它发布到comp.lang.c.moderated,但它似乎没有



我在分配表达式中有关于挥发物的问题。

我在嵌入式开发中发现了以下代码片段

论坛:


----

volatile char a;


...


if(++ a == 1)

{

...

----


此代码片段之后是两个

编译器的输出,其中一个是gcc。 Gcc的代码看起来像

这样(在RTL中,Rn表示寄存器):


R1< - * a

R1< - R1 + 1

* a< - R1

R2< - * a

IF R2 == 1


现在回答我的问题!上面的代码包含两个读取访问

和一个写入访问权限。我原以为只应该执行一次

读访问。标准是否允许

第二次读取操作?


我添加了许多我在尝试时使用的标准文本

推断出答案。如果可以,请帮忙!


对不起,长期发帖!


问候

/ Daniel W


Ps如果通过

电子邮件回复,请从电子邮件地址中删除下划线!


---------------- --------------------------------------------

从标准ISO / IEC [9899:1999]中读取我发现

以下与此问题相关的段落(A表示

基本原理,B表示标准) :


B.5.1.2.3 - 2访问易失性对象,修改对象,

修改文件,或调用任何函数那些

操作都是副作用,这是执行环境状态的变化。对表达式的评价可能会产生副作用。在执行

序列中的某些指定点称为序列点,之前

评估的所有副作用都应完整,后续没有副作用

应进行评估。 ...


B.6.5.16 - 3赋值运算符将值存储在左操作数指定的

对象中。赋值表达式

具有赋值后左操作数的值,但是

不是左值。赋值表达式的类型是左操作数的类型

,除非左操作数具有限定类型,

在这种情况下它是类型的非限定版本

左操作数。更新左操作数的存储值的副作用应发生在前一个和下一个

序列点之间。


B.6.5.16.2 - 3形式E1 op = E2

的复合赋值不同于简单赋值表达式E1 = E1 op E2 only

因为左值E1仅被评估一次。


B.6.3.2.1 - 2除非它是sizeof运算符的操作数,否则

the unary&运算符,++运算符, - 运算符,或者左边的
操作数。运算符或赋值运算符,

没有数组类型的左值被转换为存储在

指定对象中的值(并且不再是左值)。如果左值具有

限定类型,则该值具有左值类型的非限定版本

;否则,该值具有左值的类型。如果

左值的类型不完整且没有数组类型,则

行为未定义。


B .6.5.3.1 - 2前缀++运算符的操作数的值

递增。结果是

增量后操作数的新值。表达式++ E等价于(E + = 1)。参见

关于加法运算符和复合赋值的讨论

有关约束,类型,副作用和转换的信息

以及操作的影响指针。


B.6.7.3 - 3与限定类型相关联的属性是

仅对于作为左值的表达式有意义。


B.6.7.3 - 6具有volatile限定类型的对象可能是以实现未知的方式修改的b $ b b b或其他

未知的副作用。因此,任何引用此类对象的表达式都应严格按照抽象机器的规则进行评估,如5.1.2.3所述。此外,

每个序列点,对象中存储的值应与抽象机器规定的值一致,除非经修改后的

by前面提到的未知因素。什么构成

访问具有volatile限定类型的对象是

实现定义。


附件C在标准中,在选择陈述的控制

表达之后放置一个亮点。


A.6.5.2.4C89委员会没有认可练习一些

实现考虑后增量和后减量

运算符表达式为左值。


A .6.5.3.1见6.5.2.4。


A.6.5.16保理分配的优化规则可以

也可以说明。设X(i,S)是一个不包含

不纯函数或有序运算符的表达式,并假设X

包含一个存储S(i)到i的集合我要知道(i)并返回

Sval(i)。可能的表达式是


S(i):Sval(i):Snew(i):

++ i i + 1 i + 1

i ++ i i + 1

- i i-1 i-1

i-- i i-1

yyy

i op = yi op yi op y


然后X(i,S)可以替换为


(T = i,i = Snew(i),X(T,Sval))





(T = X (i,Sval),i = Snew(i),T)


前提是i和y本身都没有副作用。

Hi!

I tried to post this to comp.lang.c.moderated but it didn''t
seem to go through.

I''ve got a question about volatiles in assignment expressions.
I found the following code snippet in an embedded development
forum:

----
volatile char a;

...

if (++a == 1)
{
...
----

This code snippet was then followed by the output from two
compilers, one which was gcc. Gcc''s code looked like something
like this (in RTL like form where Rn denotes a register):

R1 <- *a
R1 <- R1 + 1
*a <- R1
R2 <- *a
IF R2 == 1

Now to my question! The code above contains two read accesses
and one write access to a. I would have assumed that only one
read access should be performed. Does the standard allow the
second read operation?

I am adding a lot of standard texts that I''ve used when trying
to deduce the answer. Please help if you can!

Sorry for the long posting!

Regards
/Daniel W

P.s. Remove underscores from e-mail address if replying via
e-mail!

------------------------------------------------------------
Reading from the standard ISO/IEC [9899:1999] I find the
following passages related to this issue (A denotes the
rationale and B denotes the standard):

B.5.1.2.3 - 2 "Accessing a volatile object, modifying an object,
modifying a file, or calling a function that does any of those
operations are all side effects, which are changes in the state
of the execution environment. Evaluation of an expression may
produce side effects. At certain specified points in the execution
sequence called sequence points, all side effects of previous
evaluations shall be complete and no side effects of subsequent
evaluations shall have taken place." ...

B.6.5.16 - 3 "An assignment operator stores a value in the
object designated by the left operand. An assignment expression
has the value of the left operand after the assignment, but is
not an lvalue. The type of an assignment expression is the type
of the left operand unless the left operand has qualified type,
in which case it is the unqualified version of the type of the
left operand. The side effect of updating the stored value of
the left operand shall occur between the previous and the next
sequence point."

B.6.5.16.2 - 3 "A compound assignment of the form E1 op= E2
differs from the simple assignment expression E1 = E1 op E2 only
in that the lvalue E1 is evaluated only once."

B.6.3.2.1 - 2 "Except when it is the operand of the sizeof operator,
the unary & operator, the ++ operator, the -- operator, or the left
operand of the . operator or an assignment operator, an lvalue that
does not have array type is converted to the value stored in the
designated object (and is no longer an lvalue). If the lvalue have
qualified type, the value has the unqualified version of the type
of the lvalue; otherwise, the value has the type of the lvalue. If
the lvalue has an incomplete type and does not have array type, the
behavior is undefined."

B.6.5.3.1 - 2 "The value of the operand of the prefix ++ operator
is incremented. The result is the new value of the operand after
incrementation. The expression ++E is equivalent to (E+=1). See
discussions of additive operators and compound assignment for
information on constraints, types, side effects, and conversions
and the effects of operations on pointers."

B.6.7.3 - 3 "The properties associated with qualified types are
meaningfull only for expressions that are lvalues."

B.6.7.3 - 6 "An object that has volatile-qualified type may be
modified in ways unknown to the implementation or have other
unknown side effects. Therefore any expression refering to such
an object shall be evaulated strictly according to the rules of
the abstract machine, as described in 5.1.2.3. Furthermore, at
every sequence point the value stored in the object shall agree
with that prescribed by the abstract machine, except as modified
by the unknown factors mentioned previously. What constitutes
an access to an object that has volatile-qualified type is
implementetion-defined."

Annex C in the standard places a sequnce point after the controlling
expression of a selection statement.

A.6.5.2.4 "The C89 Committee did not endorse the practice in some
implementations of considering post-increment and post-decrement
operator expressions to be lvalues."

A.6.5.3.1 "See 6.5.2.4."

A.6.5.16 "The optimization rules for factoring out assignments can
also be stated. Let X(i,S) be an expression which contains no
impure functions or sequenced operators, and suppose that X
contains a storage S(i) to i which sets i to Snew(i) and returns
Sval(i). The possible expressions are

S(i): Sval(i): Snew(i):
++i i+1 i+1
i++ i i+1
--i i-1 i-1
i-- i i-1
y y y
i op= y i op y i op y

Then X(i,S) can be replaced by either

(T = i, i = Snew(i), X(T,Sval))

or

(T = X(i,Sval), i = Snew(i), T)

provided that neither i nor y have side effects themselves."

推荐答案

Daniel W< _R ********* @ hotmail.com>写道:
Daniel W <_R*********@hotmail.com> writes:
我试图将它发布到comp.lang.c.moderated但它似乎没有通过。
I tried to post this to comp.lang.c.moderated but it didn''t
seem to go through.




文章出现在comp.lang.c.moderated上,当主持人获得发布它们时,
。你的问题最终可能会显示出来(长期

你的问题在这里得到了解答)。


-

Keith汤普森(The_Other_Keith) ks***@mib.org < HTTP://www.ghoti.net/~kst> <无线电通信/>
圣地亚哥超级计算机中心< *> < http://users.sdsc.edu/~kst>

我们必须做点什么。这是事情。因此,我们必须这样做。



Articles appear on comp.lang.c.moderated when the moderator gets
around to posting them. Yours will probably show up eventually (long
after your question has been answered to death here).

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.





Daniel W写道On 03/07/06 10:17,:


Daniel W wrote On 03/07/06 10:17,:

我对分配表达式中的挥发性有疑问。
我在嵌入式开发论坛中找到了以下代码片段:
----
volatile char a;



if(++ a == 1)
{
...
----

此代码片段之后是两个
编译器的输出,其中一个是gcc。 Gcc的代码看起来像是这样的东西(在RTL中表示Rn表示寄存器):

R1< - * a
R1< - R1 + 1
* a< - R1
R2< - * a
IF R2 == 1

现在回答我的问题!上面的代码包含两个读访问和一个写访问。我原以为只应该执行一次读取访问。标准是否允许第二次读取操作?


从标准ISO / IEC [9899:1999]读取我发现
以下与此问题相关的段落(A表示基本原理,B表示标准):
[...]
B.6.5.16 - 3赋值运算符存储值左操作数指定的对象。赋值表达式
具有赋值后左操作数的值,但不是左值。 [...]

I''ve got a question about volatiles in assignment expressions.
I found the following code snippet in an embedded development
forum:

----
volatile char a;

...

if (++a == 1)
{
...
----

This code snippet was then followed by the output from two
compilers, one which was gcc. Gcc''s code looked like something
like this (in RTL like form where Rn denotes a register):

R1 <- *a
R1 <- R1 + 1
*a <- R1
R2 <- *a
IF R2 == 1

Now to my question! The code above contains two read accesses
and one write access to a. I would have assumed that only one
read access should be performed. Does the standard allow the
second read operation?
[...]

Reading from the standard ISO/IEC [9899:1999] I find the
following passages related to this issue (A denotes the
rationale and B denotes the standard):
[...]
B.6.5.16 - 3 "An assignment operator stores a value in the
object designated by the left operand. An assignment expression
has the value of the left operand after the assignment, but is
not an lvalue. [...]




这似乎是模棱两可的地方:必须

赋值后的值...... ;从

volatile l.h.s.中读取(似乎是gcc的解释),或者

将分配给l.h.s.的值足够(你的)?


gcc阅读似乎是可辩护的:之后毕竟意味着之后,

。也许变量实际上是一个特殊的硬件

小工具,它连接到一个I / O设备:你给它写了一个

命令代码,当你读到它时从它你回来

不是写的,而是某种设备状态。那个

是,读取的值可能与写入的值不一样。


-
Er ********* @ sun.com



This seems to be where the ambiguity creeps in: must
"the value ... after the assignment" be read from the
volatile l.h.s. (seems to be gcc''s interpretation), or
will the value assigned to the l.h.s. suffice (yours)?

The gcc reading seems defensible: "after" means "after,"
after all. Maybe the variable is really a special hardware
gadget that''s connected up to an I/O device: You write a
command code to it, and when you read from it you get back
not what was written, but some kind of device status. That
is, the value as read might not resemble the value written.

--
Er*********@sun.com


在2006-03-07,Daniel W< _R ********* @ hotmail.com>写道:
On 2006-03-07, Daniel W <_R*********@hotmail.com> wrote:
嗨!

我试着将它发布到comp.lang.c.moderated但它似乎没有通过。

我对分配表达式中的挥发性有疑问。
我在嵌入式开发论坛中找到了以下代码片段:

--- -
volatile char a;

...

if(++ a == 1)
{
... <这个代码片段之后是两个
编译器的输出,一个是gcc。 Gcc的代码看起来像是这样的东西(在RTL中表示Rn表示寄存器):

R1< - * a
R1< - R1 + 1
* a< - R1
R2< - * a
IF R2 == 1

现在回答我的问题!上面的代码包含两个读访问和一个写访问。


这是因为出于某种原因gcc选择再次阅读。但是,

C代码只包含一个读取访问权限 - 读取原始值

递增。 R2< - R1可能更符合原始表达式的含义,因为前缀++运算符

产生一个特定值,而不是其论点的别名。但是,因为

它会产生相同的行为。


此外,给出的RTL代码是五个语句,每个语句可能都是以

拥有序列点的rtl模拟,而不是一个。

我会假设只应执行一次读取访问。
标准是否允许第二次访问读取操作?
Hi!

I tried to post this to comp.lang.c.moderated but it didn''t
seem to go through.

I''ve got a question about volatiles in assignment expressions.
I found the following code snippet in an embedded development
forum:

----
volatile char a;

...

if (++a == 1)
{
...
----

This code snippet was then followed by the output from two
compilers, one which was gcc. Gcc''s code looked like something
like this (in RTL like form where Rn denotes a register):

R1 <- *a
R1 <- R1 + 1
*a <- R1
R2 <- *a
IF R2 == 1

Now to my question! The code above contains two read accesses
and one write access to a.
That''s because for some reason gcc chooses to read a again. However, the
C code only includes ONE read access - to read the original value which
is incremented. R2 <- R1 would probably have been more in the spirit of
the meaning of the original expression, since the prefix ++ operator
yields a specific value, not an alias for its argument. However, since
it results in the same behavior it is permitted.

Besides, the RTL code given is five statements, each presumably with its
own rtl analogue of a "sequence point", not one.
I would have assumed that only one read access should be performed.
Does the standard allow the second read operation?




该标准不管理gcc的RTL语言。在显示的C代码中只有一个

读取权限。



The standard does not govern gcc''s "RTL" language. There is only one
read access in the C code shown.


这篇关于赋值表达式中的Volatiles的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆