操作符(1)
c++的内建操作符很多。相比其它语言,c++对操作符赋予了更加重要的意义。操作符主要分为四个大类别:算术操作符、关系操作符、逻辑操作符、位操作符。另外,还有一些执行特定任务的操作符。
赋值操作符
可以在任何有效的语句中使用 = 赋值操作符。这和有些编程语言不同,如Pascal、BASIC、FOTRAN中将赋值操作符当作特别语句。赋值操作符使用的通常格式如下:
variable_name = expression;
等式的左侧,或者说赋值目标必须是变量或者指针,不可以是函数或者常数。
我们常常可以在文档资料或者编译器的错误信息中看到两个词汇:lvalue和rvalue。简单的说,lvalue就是可以出现在等式左边的对象。实际上几乎所有的lvalue都是变量。rvalue指的是可以出现在等式右侧的表达式,通常纸带表达式的值。
赋值时的数据类型转换
当一种类型的数据与另一种不同的数据类型混合运算的时候就会发生类型转换。在一个赋值语句中,数据类型转换的规则很简单,右侧的表达式的数据类型将会被转换成左侧的变量的数据类型。下面是示例:
int x;
char ch;
float f;
void func( void )
{
ch = x; /* line 1 */
x = f; /* line 2 */
f = ch; /* line 3 */
f = x; /* line 4 */
}
在第一行,变量x的高八位被丢弃,低八位存入变量ch中。如果x的数值在0到255之间,那么赋值后ch和x将会有同样的数值。反之,ch中的数值只能反映变量x的低八位的数值。在第二行中,变量x只能接收变量f的整数部分的数值。在第三行,变量ch中的数值将会被转化成浮点类型存储在f中。第四行也是类似的转换。
当字符转化为整型,或者整型转化为长整型的时候,特定数量的高位会被丢弃。在16位环境下,整型转换为字符型会丢弃高8位,长整型转换为整型会丢弃高16位。在32位环境下,整型转换位字符型会丢弃高24位,整型转换为短整型会丢弃高16位。
表2-3概括了类型转换的规则。记住,诸如整型转换为浮点型、浮点型转换为双精度型等类似的转换并没有增加准确度和精度。这些转换仅仅是改变了数值的描述类型。另外,当把char类型转换为整型或者浮点型的时候,大部分编译器把char类型的数值视为正数,不管它真正的数值是多少(也就是直接增加n位0作为高位)。不过也有些编译器,当char类型的值大于127时将其作为负数处理(也就是增加n位1作为高位)。总之,为了避免可移植性上的问题,最好还是严格的使用char处理字符,使用int、short int、signed char处理数值。
假如遇到表2-3中没有列出的转换规则,那么编译器会先进行中间转换。例如,当需要把双精度浮点型转换位整型的时候,编译器先将双精度型转换为浮点类型,再将浮点型转换为整型。
表2-3 普通类型转换
Target Type Expression Type Possible Info Loss
signed char char If value>127,target is negative
char short int High-order 8 bits
char int(16 bits) High-order 8 bits
char int(32 bits) High-order 24 bits
char long int High-order 24 bits
short int int(16 bits) None
short int int(32 bits) High-order 16 bits
int(16 bits) long int High-order 16 bits
int(32 bits) long int None
int float Fractional part and possibly more
float double Precision, result rounded
double long double Precision, result rounded
Multiple assignment(本人理解为:多重赋值)
c++允许同时在一个表达式中对多个变量进行赋值。例如:x = y = z = 0;专业的程序中常常用这种方式给多个变量赋公值。
算术操作符
表2-4列出了c++中的算术操作符。其中运算符+,-,*,/的作用在大部分语言中都是相同的,它们可以应用于几乎所有的内建数据类型。当对整型和字符型使用/操作符时,余数会被截去。例如,5/2整除的结果是整数2。c++中的模操作符%也和它在其它语言中的作用相同,它用来产生余数。不过,%操作符不能用在浮点数类型上。看下面的例子:
int x, y;
x = 5;
y = 2;
printf( "%d", x/y ); /* will display 2 */
printf( "%d", x%y ); /* will displat 1, the remainder of the integer division */
x = 1;
y = 2;
printf( "%d %d", x/y, x%y ); /* will display 0 1 */
最后一行将显示0 1,因为1整除以2结果为0,余数为1。
一元操作符-的作用是让它的操作数乘以-1。也就是说任何操作数加上-号以后都会改变符号。
表2-4. 算术操作符
Operator Action
- Subtraction, also unary minus
+ Addition
* Multiplication
/ Division
% Modulus
-- Decrement
++ Increment
自加和自减运算符
c++定义了两种其它语言中没有的运算符,它们非常有用--自减、自加运算符:--,++。++运算符将会让操作数加1,--运算符让操作数减1。
x = x + 1等价于++x
x = x - 1等价于--x
自加和自减运算符可以写在操作数前或者后。例如++x和x++都是正确的。不过,把这两个运算符写在前面还是后面也是有区别的。如果自加或自减操作符放在操作数前,那么操作数的值会首先被表达式获取,然后再加或减1。如果放在后面,则编译器会先把被操作数加或减1之后,再将结果放入表达式进行运算。例如:
x = 10;
y = x++;
这里y的值最终为10。
x = 10;
y = ++x;
这里y的值最终为11。
当然,这两种情况下最终x的值都为11。
大部分编译器中的自加和自减操作符都是快速高效的,比用一般的赋值表达式实现同样功能的速度要快的多,所以,我们在类似的情况下应该优先使用这种操作符。
下面列出了各种算术操作符的优先级:
highest ++ --
-(unary minus)
* / %
lowest + -
遇到同样优先级的操作符,编译器会从左往右进行求值,这里我们可以通过括号来改变编译器的求值顺序。括号的用法和其它语言中是一样的,括号能让一个或者一组操作符有更高的优先级。
关系和逻辑操作符
关系操作符描述了两个值之间的关系,逻辑操作符则描述了这种关系如何结合到一起。关系和逻辑操作符常常会被一起使用,所以这里把它们放在一起讨论。
true和false的概念是关系和逻辑操作符概念的基础。在C语言中,true是非零值,false是零值。使用了关系和逻辑操作符的表达式将会返回0当命题不成立,返回1当命题成立。
c++仍然支持这种0和非0代表false和true的原则。不过,c++特别定义了bool布尔数据类型和布尔常量true和false。在c++中,当需要进行数据类型转换的时候,0将会自动转换为false而非0将自动转换为true。反过来,true自动转换为1,false自动转换为0。在c++中关系和逻辑表达式产生的结果会是布尔常量。
表2-5列出了所有关系和逻辑操作符。这里我们看看逻辑操作符的真值表。
p q p&&q p||q !p
0 0 0 0 1
0 1 0 1 1
1 1 1 1 0
1 0 0 1 0
关系和逻辑操作符的优先级都低于算术操作符。例如,10>1+12等价于10>(1+12),其输出为false。可以把多个操作符连接在一个表达式中,例如:10>5&&!(10<9)||3<=4,结果为true。
表2-5. 关系和逻辑操作符
Relational Operators
Operator Action
> Greater than
>= Greater than or equal
< Less than
<= Less than or equal
== Equal
!= Not equal
Logical Operators
Operator Action
&& AND
|| OR
! NOT
尽管C语言和c++中都没有定义异或操作符(XOR),但是可以很简单的用其它逻辑操作符创建出有‘或’操作符功能的函数。XOR操作符在两个操作数的布尔值相反的情况下返回true。下面的函数实现了异或的功能:
#include <stdio.h>
int xor( int a, int b );
int main( void )
{
printf( "%d", xor(1,0) );
printf( "%d", xor(1,1) );
printf( "%d", xor(0,1) );
printf( "%d", xor(0,0) );
return 0;
}
/* perform a logical XOR operation using the two arguments. */
int xor( int a, int b )
{
return (a || b) && !(a && b);
}
下面列出了关系和逻辑操作符的优先级:
Highest !
> >= < <=
== !=
&&
Lowest ||
和在算术操作符中介绍的一样,可以利用括号改变优先级的顺序。例如:
!0&&0||0 结果为false。
!(0&&0)||0 结果为true。
记住:所有的关系和逻辑操作符表达式都返回一个布尔常量。因此,下面的代码片断不但正确,而且还会打印出1。
int x;
x = 100;
printf( "%d", x>10 );