(18)'c++:COMPLETE REFERENCE' 第一部分 第二章(表达式) 第十节
2007-03-14 18:43
323 查看
表达式
操作符,常量,变量都是表达式的组成部分.在c++中,表达式就是这些元素构成的有效的组合.C语言的表达式基本遵循一般代数规则,有几点却是与C语言紧密相关的,以下将分别加以讨论。
求值的顺序
C语言和c++都没有指定表达式中的子表达式的求值顺序的规则.这就给编译器留下了重新编排优化表达式的自由.然而,这也意味着我们编写的程序中用到表达式时,表达式的值不应该依赖于它的各个子表达式的求值顺序.例如:
x = f1() + f2();
这个表达式被编译后,无法断定到底是f1()还是f2()先被运行.
表达式的类型转换
当在一个表达式中混合使用了多种不同的常量和变量的时候,它们会经过类型转换成为统一的数据类型.编译器会将所有操作数转换为最大的数据类型,这叫做类型提升.首先,char和short int会北转换为int,这叫做整型提升.这一步结束之后,剩下的转换操作也会一步一步的进行,下面我们来描述类型转化的法则:
如果操作数是long double,那么下一个操作数将会转化为long double,
否则,如果操作数为double,下一个操作数转化为double,
否则,如果操作数为float,下一个操作数转化为float,
否则,如果操作数为unsigned long,下一个操作数转化为unsigned long,
否则,如果操作数为long,下一个操作数转化为long,
否则,如果操作数为unsigned int,下一个操作数转化为unsigned long.
有一种例外的情况:如果一个操作数类型为long,另一个是unsigned int,而这个unsigned int操作数又无法转换成用long表述,那么就直接转换为级别更高的unsigned long.当上述的类型转换规则起作用的时候,每一对操作数都会成为某个相同的数据类型,而它们求值的结果将被视为一个新的该类型的操作数,并继续在表达式中适用类型转换规则.
我们来看看图2-2中发生的类型转换.首先,char ch转换成int,且float f转换成double;然后ch/i的结果转换成double,因为f*d是double;最后由于这次两个操作数都是double,所以结果也是double.
图2-2. 类型转化的例子
强制类型转换(Casts)
可以将某个表达式的类型强制转换为指定的数据类型,这就是强制类型转换.通用格式如下:
(type)expression
type必须是有效的数据格式.例如,为了确保x/2最后的求值结果为浮点型,可以书写成如下格式:
(float)x/2
各种cast操作符都被视为一元操作符,它和其它一元操作符有相同的优先级.尽管在编程中不常使用强制类型转换,但是一旦需要的时候,它们会发挥很大的作用.例如,在下面的程序中,我们需要用到整型变量i做为循环的计数变量,i为整型,同时,又需要对i进行计算后保留小数部分,这就需要使用强制类型转换.
#include <stdio.h>
int main( void ) /* print i and i/2 with fractions */
{
int i;
for( i =1; i <= 100; ++i )
printf( "%d/2 is: %f/n", i, (float)i/2 );
return 0;
}
如果不使用强制类型转换(float),i/2后的结果会被取整.强制类型转换确保了小数部分的保留.
注: c++增加了四种强制类型转换操作符,如const_cast和static_cast,这些操作符在本书的第二部分讲解.
空格和圆括号
可以在程序代码中添加空格(space)和制表符(tab)以增加程序的可读性.例如下面的两个表达式是相同的:
x=10/y~(127/x)
x = 10 / y ~(127/x)
多余的圆括号不会降低程序运行的效率,我们应该尽量多使用括号来使得表达式的求值顺序更加明确,这便于自己或者别人阅读理解.例如,看下面的两个句子那个更容易理解?
x = y/3-34*temp+127;
x = (y/3) - (34*temp) + 127;
复合赋值操作符
赋值语句有一个变种,叫做符合赋值.可以简化某些特定的赋值操作.例如:
x = x+10;
可以写成
x += 10;
+=操作符告诉编译器把x的值加上10后再赋予x.这一复合形式适用于所有的二元操作符.通用格式如下:
var = var operator expression
可以写成
var operator= expression
要书写更专业的程序就要多使用这样的复合赋值操作符,所以我们必须对它熟悉.复合赋值操作符也常常被称为速记符,因为它们的格式非常简洁.
操作符,常量,变量都是表达式的组成部分.在c++中,表达式就是这些元素构成的有效的组合.C语言的表达式基本遵循一般代数规则,有几点却是与C语言紧密相关的,以下将分别加以讨论。
求值的顺序
C语言和c++都没有指定表达式中的子表达式的求值顺序的规则.这就给编译器留下了重新编排优化表达式的自由.然而,这也意味着我们编写的程序中用到表达式时,表达式的值不应该依赖于它的各个子表达式的求值顺序.例如:
x = f1() + f2();
这个表达式被编译后,无法断定到底是f1()还是f2()先被运行.
表达式的类型转换
当在一个表达式中混合使用了多种不同的常量和变量的时候,它们会经过类型转换成为统一的数据类型.编译器会将所有操作数转换为最大的数据类型,这叫做类型提升.首先,char和short int会北转换为int,这叫做整型提升.这一步结束之后,剩下的转换操作也会一步一步的进行,下面我们来描述类型转化的法则:
如果操作数是long double,那么下一个操作数将会转化为long double,
否则,如果操作数为double,下一个操作数转化为double,
否则,如果操作数为float,下一个操作数转化为float,
否则,如果操作数为unsigned long,下一个操作数转化为unsigned long,
否则,如果操作数为long,下一个操作数转化为long,
否则,如果操作数为unsigned int,下一个操作数转化为unsigned long.
有一种例外的情况:如果一个操作数类型为long,另一个是unsigned int,而这个unsigned int操作数又无法转换成用long表述,那么就直接转换为级别更高的unsigned long.当上述的类型转换规则起作用的时候,每一对操作数都会成为某个相同的数据类型,而它们求值的结果将被视为一个新的该类型的操作数,并继续在表达式中适用类型转换规则.
我们来看看图2-2中发生的类型转换.首先,char ch转换成int,且float f转换成double;然后ch/i的结果转换成double,因为f*d是double;最后由于这次两个操作数都是double,所以结果也是double.
图2-2. 类型转化的例子
强制类型转换(Casts)
可以将某个表达式的类型强制转换为指定的数据类型,这就是强制类型转换.通用格式如下:
(type)expression
type必须是有效的数据格式.例如,为了确保x/2最后的求值结果为浮点型,可以书写成如下格式:
(float)x/2
各种cast操作符都被视为一元操作符,它和其它一元操作符有相同的优先级.尽管在编程中不常使用强制类型转换,但是一旦需要的时候,它们会发挥很大的作用.例如,在下面的程序中,我们需要用到整型变量i做为循环的计数变量,i为整型,同时,又需要对i进行计算后保留小数部分,这就需要使用强制类型转换.
#include <stdio.h>
int main( void ) /* print i and i/2 with fractions */
{
int i;
for( i =1; i <= 100; ++i )
printf( "%d/2 is: %f/n", i, (float)i/2 );
return 0;
}
如果不使用强制类型转换(float),i/2后的结果会被取整.强制类型转换确保了小数部分的保留.
注: c++增加了四种强制类型转换操作符,如const_cast和static_cast,这些操作符在本书的第二部分讲解.
空格和圆括号
可以在程序代码中添加空格(space)和制表符(tab)以增加程序的可读性.例如下面的两个表达式是相同的:
x=10/y~(127/x)
x = 10 / y ~(127/x)
多余的圆括号不会降低程序运行的效率,我们应该尽量多使用括号来使得表达式的求值顺序更加明确,这便于自己或者别人阅读理解.例如,看下面的两个句子那个更容易理解?
x = y/3-34*temp+127;
x = (y/3) - (34*temp) + 127;
复合赋值操作符
赋值语句有一个变种,叫做符合赋值.可以简化某些特定的赋值操作.例如:
x = x+10;
可以写成
x += 10;
+=操作符告诉编译器把x的值加上10后再赋予x.这一复合形式适用于所有的二元操作符.通用格式如下:
var = var operator expression
可以写成
var operator= expression
要书写更专业的程序就要多使用这样的复合赋值操作符,所以我们必须对它熟悉.复合赋值操作符也常常被称为速记符,因为它们的格式非常简洁.
相关文章推荐
- (10)'c++:COMPLETE REFERENCE' 第一部分 第二章(表达式) 第二节
- (15)'c++:COMPLETE REFERENCE' 第一部分 第二章(表达式) 第七、八节
- (11)'c++:COMPLETE REFERENCE' 第一部分 第二章(表达式) 第三节
- (14)'c++:COMPLETE REFERENCE' 第一部分 第二章(表达式) 第六节
- (16)'c++:COMPLETE REFERENCE' 第一部分 第二章(表达式) 第九节操作符(1)
- (19)'c++:COMPLETE REFERENCE' 第一部分 第三章(语句) 第一节
- (24)'c++:COMPLETE REFERENCE' 第一部分 第三章(语句) 第五节
- (29)'c++:COMPLETE REFERENCE' 第一部分 第四章(数组和以空字符结束的字符串) 第四节
- (33)'c++:COMPLETE REFERENCE' 第一部分 第四章(数组和以空字符结束的字符串) 第八节
- (4)'c++:COMPLETE REFERENCE' 第一部分 第一章(c语言概述) 第三节
- (22)'c++:COMPLETE REFERENCE' 第一部分 第三章(语句) 第三节(2)
- (25)'c++:COMPLETE REFERENCE' 第一部分 第三章(语句) 第六、七节
- (31)'c++:COMPLETE REFERENCE' 第一部分 第四章(数组和以空字符结束的字符串) 第六节
- (23)'c++:COMPLETE REFERENCE' 第一部分 第三章(语句) 第四节
- (30)'c++:COMPLETE REFERENCE' 第一部分 第四章(数组和以空字符结束的字符串) 第五节
- (1)'C++: THE COMPLETE REFERENCE' --第一部分 前言
- (2)'c++:COMPLETE REFERENCE' 第一部分 第一章(c语言概述) 第一节
- (5)'c++:COMPLETE REFERENCE' 第一部分 第一章(c语言概述) 第四节
- (26)'c++:COMPLETE REFERENCE' 第一部分 第四章(数组和以空字符结束的字符串) 第一节
- (32)'c++:COMPLETE REFERENCE' 第一部分 第四章(数组和以空字符结束的字符串) 第七节