6.5.16 赋值操作符

语法

1、assignment-expression:

conditional-expression

unary-expression    assignment-operator     assignment-expression

assignment-operator: 以下之一

        =    *=    /=    %=    +=    -=    <<=    >>=    &=    ^=    |=

约束

2、一个赋值操作符应该具有一个可修改的左值作为其左操作数。

语义

3、一个赋值操作符将一个值存储在由左操作数所指派的对象中。一个赋值表达式在赋值后具有左操作数的值,[注:允许实现读此对象以确定该值,但不要求这么做,即使对象是用volatile限定的类型。]但并不是一个左值。赋值表达式的类型是左操作数的类型,在左值转换后即可具有。更新左操作数所存放的值的副作用顺序在左和右操作数的值计算之后。操作数的计算是没有顺序的。

6.5.16.1 简单赋值

约束

1、要遵守下列规则之一:[注:对于这些关于类型限定符的非对称的出现是由于将左值变为“表达式的值”并移除了任一类型限定符的转换(在6.3.2.1中指定)被应用于表达式的类型类别(比如,int volatile * const移除了const,但并不移除volatile)。]

——左操作数具有原子的、限定的、或非限定的算术类型,而右操作数具有算术类型;

——左操作数具有与右操作数相兼容的一个原子的、限定的、或非限定版本的一个结构体或联合体类型;

——左操作数具有原子的、限定的、或非限定的指针类型,且(考虑到左操作数在左值转换之后将会有的类型)两个操作数都具有指向限定或非限定版本的兼容类型的指针,而被左操作数所指向的类型具有被右值所指向的类型的所有限定符。

——左操作数具有原子的、限定的、或非限定的类型,且其中一个操作数是一个指向一个对象类型的指针,而另一个是一个指向一个限定或非限定版本的void的指针,而被左操作数所指向的类型具有被右操作数所指向类型的所有限定符。

——左操作数是一个原子的、限定的、或非限定的指针,而右操作数是一个空指针常量;或

——左操作数具有原子的、限定的、或非限定的_Bool,而右操作数是一个指针。

语义

2、在简单赋值(=)中,右操作数的值被转换为赋值表达式的类型,并替换由左操作数所指派的对象中的值。

3、如果正要存在一个对象中的值从另一个对象被读,两者以任一种形式叠交,那么该叠交应该是准确的,且两个对象应该具有一个兼容类型的限定或非限定版本;否则,行为是未定义的。

4、例1 在下列程序片段中

int f(void);
char c;
/* ... */
if( (c = f()) == -1 )
/* ... */

由函数所返回的int值可以被截断,当存储在char中时,然后在比较之前被转换回int宽度。在某一实现中,其“平凡的”char具有与unsigned char具有相同范围(并且charint要窄),那么转换结果不能是负数,这样比较的操作数可能永远不会比较为相等的。从而,对于充分的可移植性,变量c应该被声明为int。

5、例2 在下列程序片段中:

char c;
int i;
long l;
l = (c =i);

i的值被转换为赋值表达式c = i的类型,即char类型。在圆括号中括起来的表达式的值然后被转换为外部赋值表达式的类型,即long int类型。

6、例3 考虑以下程序片段

const char **cpp;
char *p;
const char c = 'A';
cpp = &p; // 违背了约束
*cpp = &c; // 有效
*p = ; // 有效

第一个赋值是不安全的,因为它可能允许以下有效代码企图尝试改变const对象c的值。

6.5.16.2 复合赋值

约束

1、仅对于操作符 += 以及 -=,要么左操作数应该是指向一个完整对象类型的一个原子的、限定的或非限定的指针,并且右操作数应该具有整数类型;要么左操作数应该具有原子的、限定的或非限定的算术类型,且右操作数应该具有算术类型。

2、对于其它操作符,左操作数应该具有原子的、限定的、或非限定的算术类型,并且(考虑在左值转换之后左操作数将会具有的类型)每个操作数应该具有与那些被相应二进制操作符所允许的相一致的算术类型。

语义

3、一个形式为 E1 op= E2复合赋值等价于简单的赋值表达式 E1 = E1 op (E2),除了左值E1仅被计算一次,并且关于一个不确定顺序的函数调用,一个复合赋值的操作是一单个计算。如果E1是一个原子类型,那么复合赋值是一个带有memory_order_seq_cst存储器次序语义的读-修改-写操作。[注:这里,一个指向原子对象的指针可以是一种形式,且E1E2具有整数类型,这个等价于下列代码次序,其中T1E1的类型,T2E2的类型:

T1 *addr = &E1;
T2 val = (E2);
T1 old = *addr;
T1 new;
do
{
new = old op val;
}
while(!atomic_compare_exchange_strong(adds, &old, new));

这里,new作为操作的结果。

如果E1E2具有浮点类型,那么在丢弃的对new的计算期间所遭遇的异常情况或浮点异常应该被丢弃,为了满足对E1 opE2E1 = E1 op (E2)的等价性。比如,如果附录F是有效的,所涉及的浮点类型具有IEC 60559格式,并且FLT_EVAL_METHOD为0,那么等价的代码将会是:

#include <fenv.h>
#pragma STDC FENV_ACCESS ON
/* ... */
fenv_t fenv;
T1 *addr = &E1;
T2 val = E2;
T1 old = *addr;
T1 new;
feholdexcept(&fenv);
for(;;)
{
new = old op val;
if(atomic_compare_exchange_strong(adds, &old, new))
break;
feclearexcept(FE_ALL_EXCEPT);
}
feupdateenv(&fenv);

如果,FLT_EVAL_METHOD不为0,那么T2必须是一个具有E2被计算的范围与精度的类型,为了满足等价性。

ISO/IEC 9899:2011 条款6.5.16——赋值操作符的更多相关文章

  1. ISO/IEC 9899:2011 条款6.5.17——逗号操作符

    6.5.17 逗号操作符 语法 1.expression: assignment-expression expression    ,    assignment-expression 语义 2.一个 ...

  2. ISO/IEC 9899:2011 条款6.5.6——加法操作符

    6.5.6 加法操作符 语法 1.additive-expression: multiplication-expression additive-expression    +    multipli ...

  3. ISO/IEC 9899:2011 条款6.5.4——投射操作符

    6.5.4 投射操作符 语法 1.cast-expression: unary-expression (    type-name    )    cast-expression 约束 2.除非类型名 ...

  4. ISO/IEC 9899:2011 条款6.5.2——后缀操作符

    6.5.2 后缀操作符 语法 1.postfix-expression: primary-expression postfix-expression    [    expression    ] p ...

  5. ISO/IEC 9899:2011 条款6.5.15——条件操作符

    6.5.15 条件操作符 语法 1.conditional-expression: logical-OR-expression logical-OR-expression    ?    expres ...

  6. ISO/IEC 9899:2011 条款6.5.9——相等操作符

    6.5.9 相等操作符 语法 1.equality-expression: relational-expression equality-expression    ==    relational- ...

  7. ISO/IEC 9899:2011 条款6.5.5——乘法操作符

    6.5.5 乘法操作符 语法 1.multiplicative-expression: cast-expression multiplicative-expression    *    cast-e ...

  8. ISO/IEC 9899:2011 条款6.5——表达式

    6.5 表达式 1.一个表达式是操作符与操作数的一个序列,这些操作符与操作数指定了一个值的计算,或指派一个对象或一个函数,或是生成副作用,或执行上述操作的组合.对一个操作符的操作数的值计算顺序排在对该 ...

  9. ISO/IEC 9899:2011 条款3——术语、定义与符号

    3. 术语.定义与符号 1.对于此国际标准的意图,应用了以下定义.其它术语是在用斜体类型或一个语法规则左侧出现的地方定义.在本国际标准中所显式定义的术语不被假定为对其它地方所定义的类似术语的隐式引用. ...

随机推荐

  1. openstack创建实例时aborted: Block Device Mapping is Invalid

    问题产生原因: 直接先不创建新卷,点击否,待实例创建完毕后再分配卷.

  2. 《你又怎么了我错了行了吧》【Beta】Scrum meeting 3

    第三天 日期:2019/6/26 前言: 第3次会议在女生宿舍召开(前一天晚上开的) 项目全部基本测试完成,解决了多处bug,明天终于可以拿去演示了.... 1.1 今日完成任务情况.成员贡献时间及工 ...

  3. 《The One!团队》第八次作业:ALPHA冲刺(四)

    项目 内容 作业所属课程 所属课程 作业要求 作业要求 团队名称 < The One !> 作业学习目标 (1)掌握软件测试基础技术.(2)学习迭代式增量软件开发过程(Scrum) 第四天 ...

  4. matlab的poly()函数

    MATLAB中的poly()函数是用于求以向量为解的方程或方阵的特征多项式,可以直接传递多项式方程的系数矩阵. 1.poly([1 2 3])使用的举例. P=poly([1 2 3]) 可以解出P= ...

  5. Appium环境搭建(Mac)

    为什么选择Mac做自动化测试? 既可以做iOS端的测试也可以进行Android端测试 Mac运行效率相对于Win要高很多,可以真正发挥appium的功能 环境依赖 Node.js Appium App ...

  6. Stone Game

    Description There is a stone game.At the beginning of the game the player picks n piles of stones in ...

  7. 项目兼容ie8技术要点

    好久没有写博客了,因为最近公司项目要调ie8兼容,一直在忙这事,终于竣工了,跟大家分享下这老掉牙的浏览器是如何搞定的...本人新手一枚,欢迎大家指教 项目是使用的jeecg框架,后台使用的java,前 ...

  8. /etc/shells

    List of acceptable shells for chpass(1). Ftpd will not allow users to connect who are not using one ...

  9. element-ui upload上传组件问题记录

    element-ui upload上传组件遇到的问题

  10. yum和apt-get 软件包管理器的用法及区别

    yum( Yellow dog Updater, Modified)是一个在Fedora和RedHat以及SUSE中的Shell前端软件包管理器. 一般来说著名的linux系统基本上分两大类: 1.R ...