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. 《发际线总是和我作队》第九次作业:Beta冲刺Scrum Meeting3

    项目 内容 这个作业属于哪个课程 软件工程 这个作业的要求在哪里 实验十三 团队作业9:Beta冲刺与团队项目冲刺 团队名称 发际线总和我作队 作业学习目标 (1)掌握软件黑盒测试技术:(2)掌握软件 ...

  2. 导出到CSV文件

    一.手工导出导出 1.winform void DataGridViewToExcel(DataGridView dataGridView1) { SaveFileDialog saveFileDia ...

  3. jsp里导入java包的问题

    写jsp导包的时候出了两处错误(什么?特么两处,总共就一句话啊...): 新建jsp文件会自动生成一句: <%@ page language="java" import=&q ...

  4. 第142题:环形链表II

    一. 问题描述 给定一个链表,返回链表开始入环的第一个节点. 如果链表无环,则返回 null. 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始). 如果 ...

  5. 将dedecms织梦后台编辑器ckeditor更换为kindeditor,并高亮显示代码

    1.下载kindeditor,并解压到kindeditor目录,把kindeditor目录复制到dede的include目录下(ps:修改kindeditor-all-min.js.lang文件夹下z ...

  6. 最小费用流模板(zkw与spfa)

    "zkw" 费用流算法在哪些图上慢(摘自https://www.cnblogs.com/ECJTUACM-873284962/p/7744943.html) 实践中, 上面的这个算 ...

  7. 自定义菜单和高级接口-获取Access Token

    自定义菜单和高级接口都需要使用APPID和AppSecret来创建. 对应暂时没有这些权限的微信公众账号,开发者可以申请测试账号来体验和测试体验微信公众平台的所有高级接口的功能.链接 https:// ...

  8. linux 登录后有时候会出现-bash-4.1$

    转载自https://blog.csdn.net/jiedao_liyk/article/details/78470498 linux登录后有时候会出现-bash-4.1$ 造成这样的原因: 与这个用 ...

  9. YAML_08 handlers触发器

    ansible]# vim adhttp.yml --- - hosts: cache   remote_user: root   tasks:     - copy:         src: /r ...

  10. 【angularJS】学习笔记

    一.一个html中多个ng-app //对于ng-app初始化一个AngularJS程序属性的使用需要注意,在一个页面中AngularJS自动加载第一个ng-app,其他ng-app会忽略 //如果需 ...