表达式和语句
作者:互联网
一、表达式
表达式(expression)是由运算符和操作数组合构成的(操作数是运算符操作的对象)。最简单的表达式即一个单独的操作数,以此作为基础可以建立复杂的表达式,比如下面这些:
3+2
a=(2+b/3)/5
x=i++
m=25
如上,操作数可以是常量,也可以是变量,亦可以是他们的组合。一些表达式是多个较小的表达式的组合,这些小的表达式称为子表达式(subexpression)。
二、语句
语句(statement)是构造程序的基本部分。程序(program)是一系列带有某种必须的标点语句集合。一个语句是一条完整的计算机指令。在C中,语句用结束处的一个分号标示。
c=3
这只是一个表达式(它可能是一个较大语句的一个部分),而c=3;则是一个语句。
最简单的语句是空语句:;//空语句
C把末尾加上一个分号的表达式都看作是一条语句(即,表达式语句)。因此,像下面这样写也没问题:
8;
但是,这些语句在程序中什么也不做,不算是真正有用的语句。更确切y=sqrt(x);地说,语句可以改变值或调用函数:
x=25;
++x;
y=sqrt(x);
虽然一条语句(或者至少是一条有用的语句)相当于一条完整的指令,但并不是所有的指令都表示语句。例如:
x=6+(y=5);
该语句中的子表达式y=5是一条完整的指令,但是它只是语句的一部分。因为一条完整的指令不一定是一条语句,所以分号用于识别在这种情况下的语句(即,简单语句)。
三、副作用和序列点
1.副作用
副作用(side effect)。副作用是对数据对象或文件的修改。例如,以下语句
var = 99;
它的副作用是把 var 的值修改成 99。对表达式求值也可能产生副作用,例如:
se = 100
对这个表达式求值所产生的副作用就是 se 的值被修改成 100。
2.序列点
(1)序列点(sequence point)是指程序运行中的一个特殊的时间点,在该点之前的所有副作用已经结束,并且后续的副作用还没发生。
(2)C 语句结束标志——分号(;)是序列点。也就是说,C 语句中由赋值、自增或者自减等引起的副作用在分号之前必须结束。我们以后会说到一些包含序列点的运算符。任何完整表达式(full expression)运算结束的那个时间点也是序列点。所谓完整表达式,就是说这个表达式不是子表达式。而所谓的子表达式,则是指表达式中的表达式。例如:
f = ++e % 3
这整个表达式就是一个完整表达式。这个表达式中的 ++e、3 和 ++e % 3 都是它的子表达式。
四、复合语句块
1.复合语句(compoundstatement)是用花括号括起来的一条或多条语句,复合语句也称为块(block)。
2.复合语句内的变量定义是独立的,即复合语句内定义的变量不影响复合语句外的同一个标识符的变量,且复合语句内定义的变量不能供复合语句外调用,只能在复合语句外单独定义,单独使用。但是复合语句外定义的变量可以供复合语句内调用是没有问题的。复合语句内可以定义与复合语句外同一标识符的变量,且不影响,复合语句外变量的值。
3.复合语句表达式:{ [声明和语句的列表] }
语句块与简单的语句不同,语句块不用分号当作结尾。当出现语法上某处需要一条语句,但程序却需要执行多条语句时,就可以用到语句块。例如,可以在 if 语句中使用语句块,或者当循环体需要执行多条语句时,也可以使用语句块:
{ double result = 0.0, x = 0.0; // 声明 static long status = 0; extern int limit; ++x; // 语句 if ( status == 0 ) { // 新语句块 int i = 0; while ( status == 0 && i < limit ) { / ... / } // 另一个语句块 } else { / ... */ } // 第三个语句块 }
如果语句块内需要有声明,通常会把声明放在语句块的头部,在其他语句之前。然而,C99 并不强制这么做,允许将声明放在语句块内的任何地方。
在语句块内声明的名称将具有语句块作用域。换句话说,这些名称只有自声明点开始,一直到语句块结尾之前有效。在这个作用域内,这种声明会把在语句块以外声明的同名称对象隐藏起来。
同样地,动态变量的存储周期也被限制在语句块中它们生成的地方。这意味着,如果一个变量没有被声明为 static 或 extern,那么该变量的存储空间会在语句块结束之后自动被释放。
五、类型转换
1.自动转换
(1)当类型转换出现在表达式时,无论是unsigned还是signed的char和short
都会被自动转换成int,如有必要会被转换成unsignedint(如果short与int的大
小相同,unsigned
short就比int大。这种情况下,unsigned
short会被转换成
unsignedint)。在K&R那时的C中,float会被自动转换成double(目前的C不
是这样)。由于都是从较小类型转换为较大类型,所以这些转换被称为升级
(promotion)。
(2)涉及两种类型的运算,两个值会被分别转换成两种类型的更高级别。
(3)类型的级别从高至低依次是long
double、double、float、unsignedlong
long、longlong、unsignedlong、long、unsignedint、int。例外的情况是,当
long和int的大小相同时,unsignedint比long的级别高。之所以short和char类
型没有列出,是因为它们已经被升级到int或unsignedint。
(4)在赋值表达式语句中,计算的最终结果会被转换成被赋值变量的类
型。这个过程可能导致类型升级或降级(demotion)。所谓降级,是指把一
种类型转换成更低级别的类型。
(5)当作为函数参数传递时,char和short被转换成int,float被转换成 double.
与目标类型不匹配怎么办?这取决于转换涉及的类型。
待赋值的值与目标类型不匹配时,规则如下:
(1)目标类型是无符号整型,且待赋的值是整数时,额外的位将被忽略。
例如,如果目标类型是8位unsignedchar,待赋的值是原始值求模256。
(2)如果目标类型是一个有符号整型,且待赋的值是整数,结果因实现而
异。
(3)如果目标类型是一个整型,且待赋的值是浮点数,该行为是未定义
的。
如果把一个浮点值转换成整数类型会怎样?当浮点类型被降级为整数类型时,原来的浮点值会被截断。例如,23.12和23.99都会被截断为23,-23.5会被截断为-23。
2.强制转换
强制类型转换是通过类型转换运算来实现的。其一般形式为: (类型说明符) (表达式) 其功能是把表达式的运算结果强制转换成类型说明符所表示的类型。例如:
(float) a 把a转换为实型
(int)(x+y) 把x+y的结果转换为整型在使用。
强制转换时应注意以下问题:
(1)类型说明符和表达式都必须加括号(单个变量可以不加括号),如把(int)(x+y)写成(int)x+y则成了把x转换成int型之后再与y相加了。
(2)无论是强制转换或是自动转换,都只是为了本次运算的需要而对变量的数据长度进行的临时性转换,而不改变数据说明时对该变量定义的类
标签:语句,变量,int,复合,类型,表达式 来源: https://www.cnblogs.com/mz77/p/15857389.html