C语言中的序列点

序列点是程序执行序列中一些特殊的点。 当有序列点存在时,序列点前面的表达式必须求值完毕,并且副作用也已经发生, 才会计算序列点后面的表达式和其副作用。

什么是副作用?举例子来说明。

int a = 5;
int b = a ++;

在给b赋值的语句中,表达式a++就有副作用,它返回a当前的值5后,要对a进行加1的操作。

哪些符号会生成序列点呢?

","会生成序列点。

","用于把多条语句拼接成一条语句。 例如:

int b = 5;
++ b;

可由","拼接成

int b = 5, ++b;

因为","会产生序列点,所以","左边的表达式必须先求值,如果有副作用,副作用也会生效。然后才会继续处理","右边的表达式。

&&||会产生序列点

逻辑与 && 和逻辑或 || 会产生序列点。

因为&&支持短路操作,必须先将&&左边的表达式计算完毕,如果结果为false,则不必再计算&&右边的表达式,直接返回false

||&&类似。

?:中的"?"会产生序列点

三元操作符 ?:中的"?"会产生序列点。 如:

int a = 5;
int b = a++ > 5? 0 : a;

b的结果是什么?因为"?"处有序列点,其左边的表达式必须先求值完毕。 a++ > 5在和5比较时,a并没有自增,所以表达式求值为false。 因为"?"处的序列点,其左边表达式的副作用也要立即生效,即a自增1,变为6。 因为"?"左边的表达式求值为false,所以三元操作符?:返回:右边的值a。 此时a的值是6,所以b的值是6。

序列点之间的执行顺序

奇怪的C代码中给出的例子。

int i = 3;
int ans = (++i)+(++i)+(++i);

(++i)+(++i)+(++i)之间并没有序列点,它们的执行顺序如何呢? gcc编译后,先执行两个++i,把它们相加后,再计算第三个++i, 再相加。而Microsoft VC++编译后,先执行三个++i,再相加。 两者得到的结果不同,谁对谁错呢?

谁也没有错。C标准规定:两个序列点之间的执行顺序是任意的。 当然这个任意是在不违背操作符优先级和结合特性的前提下的。 这个规定的意义是为编译器的优化留下空间。

知道这个规定,我们就应该避免在一行代码中重复出现被递增的同一个变量, 因为编译器的行为不可预测。 试想如果(++i)+(++i)+(++i)换成(++a)+(++b)+(++c)(其中abc是不同的变量), 不管++a++b++c的求值顺序谁先谁后,结果都会是一致的。

原文:http://www.cnblogs.com/jiqingwu/p/c_sequence_point.html

时间: 2024-11-05 05:56:40

C语言中的序列点的相关文章

C语言中的序列点和副作用

参考: http://www.2cto.com/kf/201210/161225.html

Python中的序列

Python中有四种内建的数据结构,即列表.元组.字典.集合.其中字典和集合我会以后再写,现在先说列表和元组,它们两个和以前提到很多次的字符串, 其实都属于——序列. 一.列表(list): 1. list 是处理一组有序项目的数据结构,即你可以在一个列表中存储一个序列的项目. 列表中的项目应该包括在方括号中,这样Python 就知道你是在指明一个列表.一旦你创建了一个列表,你可以添加.删除或是搜索列表中的项目.由于你可以 增加或删除项目,我们说列表是可变的数据类型,即这种类型是可以被改变的.

C语言中随机数相关问题

用C语言产生随机数重要用到rand函数.srand函数.及宏RAND_MAX(32767),它们均在stdlib.h中进行了声明. int rand(void);//生成一个随机数 voidsrand(unsigned int seed); //为rand设置"种子"的值 srand()就是给rand()提供种子seed,如果srand每次输入的数值是一样的,那么每次运行产生的随机数也是一样的.通常的做法是以这样一句代码: srand((unsigned)time(NULL)); 来取

C语言中的三字母词

C语言中的三字母词(trigraph) 在ANSI C标准中,定义了9个三字母词(trigraph),三字母词就是几个字符的序列,合起来表示另一个字符.三字母词使C语言环境可以在缺少一些必需字符的字符集(比如,一些非常老式的键盘上没有[]{}#\^~|)上实现.也许是由于这些字符集我们基本上用不到,所以在大多数C语言的书籍中,我们都看不到对三字母词的讲解.下图列出了9个三字母词以及它们所代表的的字符. 源代码中的"三字母词",在编译阶段会被替换为"对应的字符".对于

C语言中的单引号和双引号含义

C语言中的单引号和双引号含义迥异, 用单引号引起的一个字符实际上代表一个整数,整数值对应于该字符在编译器采用的字符集中的序列值,因此,采用ASCII字符集的编译器而言,'a'的含义与0141或97严格一致. 而用双引号引起的字符串,代表的却是一个指向无名数组起始字符的指针,该数组被双引号之间的字符以及一个额外的二进制值为零的字符'\0'初始化.

C语言中容易被忽略的细节(第一篇)

前言:本文的目的是记录C语言中那些容易被忽略的细节.我打算每天抽出一点时间看书整理,坚持下去,今天是第一篇,也许下个月的今天是第二篇,明年的今天又是第几篇呢?--我坚信,好记性不如烂笔头. 1. 在C语言中,符号之间的空白(包括空格符.制表符或换行符)将被忽略.但一个符号的中间不能有空白,否则可能被解释为另一个或几个符号.以下两种写法是等价的: //写法1 if (x > big) big = x; //写法2 if ( x > big ) big = x ; 2.编译器将程序分解为符号的&q

[整理]C语言中字符常量与ASCII码

所有的ASCII码都可以用"\"加数字(一般是8进制数字)来表示.而C中定义了一些字母前加"\"来表示常见的那些不能显示的ASCII字符,如\0,\t,\n等,就称为转义字符,因为后面的字符,都不是它本来的ASCII字符意思了. C语言中提供的所有的转码序列(转义字符序列): 转义字符 意义 ASCII码值(十进制) \a 响铃(BEL) 007 \b 退格(BS) ,将当前位置移到前一列 008 \f 换页(FF),将当前位置移到下页开头 012 \n 换行(LF

简述Python语言的元组序列结构

序列是程序设计中经常用到的数据存储方式,几乎每一种程序设计语言都提供了表格数据结构,如C和Basic中的一维.多维数组等.Python语言提供的序列类型在所有程序设计语言中是最丰富,最灵活,也是功能最强大的. 序列是一系列连续值,它们通常是相关的,并且按一定顺序排列.Python中常用的序列结构有列表.元组等. 元组和列表类似,但属于不可变序列,元组一旦创建,用任何方法都不可以修改其元素. 元组的定义方式和列表相同,但定义时所有元素是放在一对圆括号"("和")"中,

C语言中函数的分类

在C语言中函数被分为两类,一类是系统提供的标准函数,又称库函数.标准函数由系统定义,在程序中可以直接调用,例如:printf(),scanf()等.另一类是用户自己定义的函数. 用户自己定义函数要遵循一定的规则,而且定义函数它一般的格式如下: 函数类型 函数名称(形式参数表){ 说明语句序列 可执行语句序列 } 通常函数类型与函数的返回值的类型一致,函数名称的命名规则同变量命名完全一样.形式参数表是用于调用函数和被调用函数之间的数据传递,因此它也需要进行类型说明. 例如: #include <s