C#基本语法(四):运算符和表达式
1.运算符
C#提供了大量的运算符,按需要操作数的数目来分:一元运算符(如++);二元运算符(如+,*);三元运算符(如? : )。
按运算功能来分,基本的运算符可以分为以下几类:(1) 算术运算符;(2) 关系运算符;(3) 逻辑运算符 ;(4) 位运算符;(5)赋值运算符;(6)条件运算符;(7)其它(分量运算符 ' .' ,下标运算符 ' [ ]'等)
(1)算术运算符
1.算术运算符作用的操作数类型可以是整型也可以是浮点型,运算符如下表所示:
运 算 符 | 含义 | 示例(假设x,y是某一数值类型的变量) |
+ | 加 | x+y; x+3 |
- | 减 | x-y; y-3 |
* | 乘 | x*y; 4*3 |
/ | 除 | x/y; 5/3; 5.0/2.0 |
% | 取模 | x%y; 11%3; 11.0%3 |
++ | 递增 | ++x; x++; |
-- | 递减 | --x; x--; |
其中:
①“+-*/ ”运算与一般代数意义及其他语言相同,但需要注意:当“/”作用的两个操作数都是整型数据类型时,其计算结果也是整型。例如:
4/2 // 结果等于2
5/2 // 结果等于2
5/2.0 // 结果等于2.5
②“%”取模运算,即获得整数除法运算的余数,所以也称取余。例如:
11%3 // 结果等于2
12%3 // 结果等于0
11.0%3 // 结果等于2,这与C/C++不同,它也可作用于浮点类型的操作数
③“++”和“--”递增和递减运算符是一元运算符,它作用的操作数必须是变量,不能是常量或表达式。它既可出现在操作数之前(前缀运算),也可出现在操作数之后(后缀运算),前缀和后缀有共同之处,也有很大区别。例如:
++x // 先将x加一个单位,然后再将计算结果作为表达式的值。
x++ // 先将x的值作为表达式的值,然后再将x加一个单位
不管是前缀还是后缀,它们操作的结果对操作数而言,都是一样的,操作数都加了一个单位,但它们出现在表达式运算中是有区别的。例如:
int x , y ;
x=5 ; y=++x ; // x和y的值都等于6
x=5 ; y=x++ ; // x的值是6,y的值是5
(2)关系运算符
关系运算符用来比较两个操作数的值,运算结果为布尔类型的值(true或false),如下表所示。
运 算 符 | 操 作 | 结果(假设x,y是某相应类型的操作数) |
> | x>y | 如果x大于y,则为true,否则为false |
>= | x>=y | 如果x大于等于y,则为true,否则为false |
< | x<y | 如果x小于y,则为true,否则为false |
<= | x<=y | 如果x小于等于y,则为true,否则为false |
== | x==y | 如果x等于y,则为true,否则为false |
!= | x!=y | 如果x不等于y,则为true,否则为false |
如果操作数是string类型的,则在下列两种情况下被视为两个string值相等。
①两个值均为null。
②两个值都是对字符串实例的非空引用,这两个字符串不仅长度相同,并且每一个对应的字符位置上的字符也相同。
例如:
string s1="ABCD", s2="1234" , s3 = "ABCD" ;
s1 ==s2; // 结果为false
s1 ==s3; // 结果为true
(3)逻辑操作符
C#语言提供了四种逻辑操作符: 逻辑与(&&),逻辑或(||)、逻辑非(!)和逻辑判断(?:),其中逻辑与和逻辑或是二元操作符,逻辑非是一元操作符,而逻辑判断是三元操作符。
a | b | !a | a&&b | a||b |
true | true | false | true | true |
true | false | false | false | true |
false | true | true | false | true |
false | false | true | false | false |
位运算符如下表所示,借助这些位运算符可以完成对整型数的某一位测试、设置以及对一个数的位移动等操作,这对许多系统级程序设计是非常重要。
运算符 | 含义 | 运算符 | 含义 |
& | 按位与 | ~ | 按位取反 |
| | 按位或 | >> | 右移 |
^ | 按位异或 | << | 左移 |
按位与、按位或、按位异或、按位取反运算与前面介绍的与之相应的逻辑运算符的与、或、异或、取反操作含义相同,只不过位运算把这种操作作用到每一个二进制位上,逻辑运算的真或假值对应位运算的位的1或0值。例如:
在实际使用中,按位与通常用于将某位置0或测试某位是0还是1;按位或通常用于将某位置1。 例如:
ushort n;
n=0x17ff ;
if ( (n & 0x8000) == 0 )
Console.WriteLine ("最高位第十五位为0" ) ;
else
Console.WriteLine ("最高位第十五位为1" ) ;
n = (ushort)(n & 0x7fff); //n 的最高位(第15位)置0,其它位不变
n = (ushort)(n | 0x8000); //n 的最高位(第15位)置1,其它位不变
按位异或运算有一个特别的属性,假设有两个整型数x和 y,则表达式 (x ^ y) ^ y值还原为x,利用这个属性可以创建简单的加密程序。例如:
public static void Main( )
{
char ch1 = 'O' , ch2 = 'K' ;
int key = 0x1f;
Console.WriteLine ("明文:" + ch1 + ch2 ) ;
ch1 = (char) (ch1 ^ key ) ;
ch2 = (char) (ch2 ^ key ) ;
Console.WriteLine ("密文:" + ch1 + ch2 ) ;
ch1 = (char) (ch1 ^ key ) ;
ch2 = (char) (ch2 ^ key ) ;
Console.WriteLine ("解码:" + ch1 + ch2 ) ;
}
移位运算符有两个:一个左移(<<),一个右移(>>)。其基本形式为:
value << num_bits
value >> num_bits
左操作数value是要被移位的值,右操作数num_bits是要移位的位数。
左移是将给定的value向左移动num_bits位,左边移出的位丢掉,右边空出的位填0。例如:
0x1A << 2;
0x1A(十进制26)经过左移2位运算,结果值是0x68(十进制104),相当于对0x1A的值乘以 。但如果左移丢掉的位含有1,那么左移之后的值可能反而会变小。例: 0x4A << 2 ;
右移是将给定的value向右移动num_bits位,右边移出的位丢掉,左边空出的位要根据value的情况填0或1。若value是一个无符号数,左边补0;若value是一个带符号数,则按符号(正数为0,负数为1)补。 例: 0x77 >> 2 ;
0x8A >> 2 ;
(4)赋值运算符
①简单赋值运算符
语法形式:var = exp
赋值运算符左边的称为左值,右边的称为右值。右值是一个与左值类型兼容的表达式(exp),它可以是常量、变量或一般表达式。左值必须是一个已定义的变量或对象(var),因为赋值运算就是将表达式的值存放到左值,因此左值必须是内存中已分配的实际物理空间。例如:
int a=1;
int b=++a; // a的值加1赋给了b
如果左值和右值的类型不一致,在兼容的情况下,则需要进行自动转换(隐式转换)或强制类型转换(显式类型转换)。一般原则是,从占用内存较少的短数据类型向占用内存较多的长数据类型赋值时,可以不做显式的类型转换,C#会进行自动类型转换,反之当从较长的数据类型向占用较少内存的短数据类型赋值时,则必须做强制类型转换。例如:
int a=2000;
double b=a; // 隐式转换,b等于2000
byte c=(byte)a; // 显示转换,c等于208
②复合赋值运算符
在进行如x = x +3 运算时,C#提供一种简化方式x +=3,这就是复合赋值运算。
语法形式: var op= exp
除了关系运算符,一般二元运算符都可以和赋值运算符在一起构成复合赋值运算。
③条件运算符
语法形式: exp1 ? exp2 : exp3
其中,表达式exp1的运算结果必须是一个布尔类型值,表达式exp2和exp3可以是任意数据类型,但它们返回的数据类型必须一致。
首先计算exp1的值,如果其值为true,则计算exp2值,这个值就是整个表达式的结果;否则,取exp3的值作为整个表达式的结果。例如:
z = x > y ? x : y ; //z的值就是x,y中较大的一个值
z = x >=0 ? x : -x ; //z的值就是x的绝对值
④特殊运算符
new 操作符:new 操作符用于创建一个新的类型实例
typeof 操作符:typeof 操作符用于获得系统原型对象的类型,例如:typeof(int)、typeof(System.Int32) 、typeof(string)、typeof(double);
上面四个表达式的输出分别是:Int32 、 Int32 、string 、double
checked和unchecked 操作符:checked 和unchecked 操作符用于整型算术运算时控制当前环境中的溢出检查 。
⑤运算符优先级
当表达式包含多个运算符时,运算符的优先级控制各运算符的计算顺序。例如,表达式 x + y * z 按 x + (y * z) 计算,显然 * 运算符的优先级比 + 运算符高。
类 别 | 计算顺序 | 运 算 符 |
基本 | 高 低 | () [] new typeof checked unchecked |
一元 | ++ -- + - ! ~ | |
乘除 | * / % | |
加减 | + - | |
位移 | << >> | |
关系 | < > <= >= | |
相等 | == != | |
逻辑 AND | & | |
逻辑 XOR | ^ | |
逻辑 OR | | | |
条件 AND | && | |
条件 OR | || | |
条件 | ?: | |
赋值 | = *= /= %= += -= <<= >>= &= ^= |= |
⑥关系运算符优先级
关系运算符的优先级总结出如下几点:
① (<,>,<=,>=)这4种关系运算符优先级相同,而(==,!=)这2种关系运算符的优先级相同。前4种高于后2种。
②关系运算符的优先级低于算术运算符。
③关系运算符的优先级高于赋值运算符。
关系运算符优先级
①a > b + c 等效于 a > (b + c)
②a + b != a * b 等效于 (a + b) != (a * b)
③ a == b > c 等效于 a == (b > c) (a必须为一个bool值)
④a = b > c 等效于 a = (b > c) (a必须为一个bool值)
⑦逻辑表达式和运算符优先级
用逻辑运算符将关系表达式或逻辑量连接起来就是逻辑表达式。逻辑表达式的值是一个bool值,也就是说,它只能返回true或false。在一个逻辑表达式中,通常使用3种运算符,按优先级从高到低的顺序进行如下排列。
①! 逻辑非
②&& 逻辑与
③|| 逻辑或
⑧逻辑表达式和运算符优先级
① a > b && x > y 的计算顺序为:(a > b) && (x > y)
②a == b || x == y 的计算顺序为:(a == b) || (x == y)
③ !a || a > b 的计算顺序为:(!a) || (a > b)