运算符与表达式

运算符与表达式

1.运算符 
什么运算符?
	用来进行某种运算的符号
如:
+ - * / %
    几目运算符?该运算符需要带几个操作数 
	单目运算符:该运算符只需要带一个操作数。如:++ --
	双目运算符:该运算符需要带两个操作数。 如:+ - * /
	三目运算符: 该运算符需要带三个操作数。 如:?: 
结合性:决定先算谁后算谁的问题 
	从左到右结合,从右到左结合
	如:
		+ 结合性:从左到右结合 
		a+b
			先算表达式a的值,再算表达式b的值
			最后a+b 
			
		so,在C语言中 
		a+b 和 b+a的含义是不一样的
		
		例子:
		i=5,j=6;
		(i++)+(i+j) //5+12 17
		(i+j)+(i++) //11+5 16
		
优先级:	在一个含有多个运算符的表达式中,先算哪个运算符 后算
	哪个运算符的问题
	
	单目运算符>算术运算符>关系运算符>逻辑运算符>
		条件运算符>赋值运算符>逗号运算符

(1)算术运算符:进行算术运算的运算符
	++ --:单目运算符 
	* / % + -:双目运算符 结合性从左到右。
		例子:
			3+5 =>8 
			5/4 =>1(整数进行算术运算结果为整数)
			5.0/4 (5*1.0/4) ==>1.25 
			typeof(1.0)==>double 
				
			(double)(3/2) ==> 1.0
			(double)3/2 ===> 1.5
			
			用C语言的表达式来描述数学表达式
				a/b ==> 1.0*a/b
			
			%:取余,取模。要求两个操作数都必须为整数
			5%1.0 ==> error
			5%4 =>1
			4%5 =>4
			
			结合性的问题:
				a+b 和b+a在C语言中的含义是不一样的!!!!
			
			++:自增运算符
				i++
				++i
			--: 自减运算符
				i--
				--i
				
				++ --单目运算符,要求操作数必须为一个左值 lvalue
					左值:可写的地址 
					变量具备左值的。
				
				5++ error 
				(a+b)++ error  
				(a++)++ error 
					表达式的值       做完表达式后i的值
		i++            i                 i=i+1
		++i            i+1               i=i+1
		i--             i                i=i-1
		--i            i-1               i=i-1  
		例子:
			a.i=5;  
			  //a=i++;//把表达式(i++)的值,赋值给a
			  //i++这个表达式的值i 5
			  //做完表达式后i的值 i=i+1 6
			  a=++i;//把表达式(++i)的值,赋值给a
				//++i这个表达式的值i+1 6
			  //做完表达式后i的值 i=i+1 6
			b.
				i=6;
				(i++)+(i++)+(i++) 
				拒绝做这种题目!!!
				因为这种题目没有任何实际意义!!!
				哪个公司的程序员写这种代码,应该早就被辞退了。
(2)关系运算符:
	用来判断两个东东关系的运算符
	“关系”:数值大小的关系  
	< <= > >=
	== !=
	双目运算符,结合性从左到右结合
	
	关系表达式:用关系运算符连接的式子
	关系表达式的值:
		“关系成立” 1
		“关系不成立” 0
	如:
		5>4 1
		3<=2 0
		
		5>4>3
			这是一个合法的关系表达式
			<==> (5>4)>3
				拿表达式5>4的值去和3进行PK
				==> 5 >4 1
					1 >3 0
		在C语言中,5>4>3这个表达式和数学上 5>4>3
		的含义是不一样的 
		在C语言中,5>4>3拿表达式5>4的值去和3进行比较 
		
		数学上的5>4>3的含义视?
		5>4 并且4>3
		
		“并且” 如何描述呢?
		
(3)逻辑运算符	:描述逻辑关系的运算符
	! 逻辑非  单目运算符 “取反”
	&& 逻辑与  双目运算符 “并且”  结合性从左到右
	|| 逻辑或  双目运算符 “或者”  结合性从左到右
	
	逻辑表达式:用逻辑运算符连接起来的式子
	逻辑表达式的值:
		逻辑真 非0
		逻辑假 0
	例子:
		a = 4,b=5
		a&&b==>1
		a&&0==>0
		
		(3+5)||(0) ==> 1
		!a || b ==>1
		4&&0||2 ==>1
		5>3 && 8<4
		1&&0 ==> 0
		
	练习:分析如下程序的输出结果
	int a,b,c,d,m,n;
	a=1;
	b=2;
	c=3;
	d=4;
	m=1;
	n=1;
	(m=a>b)&&(n=c>d);
	printf("%d %d %d %d %d %d\n",a,b,c,d,m,n);//1 2 3 4 0 1
	
	C语言运算符是“惰性运算”
		a.a&&b&&c
		只有a为真,才会去判断b的值
		只有a和b都为真的时候,才会去判断c的值
		b.a||b||c
		只要a为真,就不必判断b和c的值
		只有a为假,才会去判断b得到值
		只有a和b都为假,才会去判断c的值
		
		一句话。如果事先已经知道表达式的值,那么后面
		的运算符(或表达式)就不需要执行。
		这就是C语言运算符的惰性。
		
	练习:
		用逻辑表达式来判断y(年份)是否为闰年:
		1)能被4整除,但是不能被100整除
		2)能被400整除
		能满足上述条件之一,就是闰年。
		
		怎么判断一个数能不能被整除 
		就是看它的余数 如果余数为0 就能被整除
		a%4 == 0 a能够被4整除
		1) 
			0 == y%4 && y%100
			
		2)	y%400==0
			 
		==>(y%4==0 && y%100)||(y%400==0)
		如果要判断不是闰年 用逻辑表达式来表示:
		!((y%4==0 && y%100)||(y%400==0))
		
(4)位运算符		
	位运算符是按bit位来进行的运算。 
	位运算符要求操作数是整数。
	有如下:
	& 按位与
	| 按位或
	^ 按位异或
	~ 按位取反
	<<按位左移
	>>按位右移
	除了~是单目运算符之外,其他位运算符都是双目运算符,结合性都是从左到右
	位运算符操作位只能是整数(整型,字符型)
	所有的位运算都是需要把操作数变成bit序列,然后再按bit位来运算。
	~ 按位取反 :单目运算符
	0 ->1
	1 ->0
	
	int a=~3;
	printf("%d\n",a);//-4
	printf("%u\n",a);//2^32-4
		3:
		00000000 00000000 00000000 00000011
		~3:
		11111111 11111111 11111111 11111100
		
	%d 
		11111111 11111111 11111111 11111100
		逆运算
		11111111 11111111 11111111 11111011
		00000000 00000000 00000000 00000100
	
	int a=~(-3);
	printf("%d\n",a);//2
	printf("%u\n",a);//2
		-3:
		11111111 11111111 11111111 11111101
		~(-3):
		00000000 00000000 00000000 00000010
	
	& 按位与:双目运算符  “与”
	a      b      a&b
	0      0       0
	1      0       0
	0      1       0
	1      1       1
	
	&如果两个Bit位操作数都为1,结果才为1,否则为0
	int a = 3&5;
		0000 0011
		0000 0101
		0000 0001
	
	练习:
		假设有一个整型变量a,要把a的第6位变为0,其他位不变
		该如何操作,请写出表达式
		a&(~(1<<6)) 0000 0001 << 6 	0100 0000 64 ~64
		a&(~64)
	
	结论:
	一个bit位与0进行“按位与 &”操作 结果为0
	x&0 == 0
	
	一个bit位与1进行“按位与 &”操作 保留原值
	x&1 == x
	
	(-3)&(-5) =?  //-7
	-3:11111111 11111111 11111111 11111101
	-5:11111111 11111111 11111111 11111011
	   11111111 11111111 11111111 11111001
	   11111111 11111111 11111111 11111000
	   00000000 00000000 00000000 00000111
	   
	| 按位或:双目运算符 结合性从左到右
		a    b   a|b
		0   0     0
		1   0     1
		0   1     1
		1   1     1
		按位或,只要有一个Bit操作数为1,其结果就是1
		3 | 5 == 7
		011
		101
		111
	
	练习:
		有一个整型变量a,要使a的第5bit置1,保持其他位不变,
		该如何操作,请写出表达式
		a|32     a|(1<<5)
		0010 0000 
	
	结论:	
		一个bit位与0进行“按位或 |”操作 保留原值 
		x | 0 == x 
		一个bit位与1进行“按位或 |”操作 结果为1
		x | 1 == 1
	
^ (按位异或):双目运算符 ,结合性从左到右
	"异或"求异 不同为1,相同为0
	a        b       a^b
	0       0          0
	1       1          0
	1       0          1
	0       1          1
		2 ^ 32 = ? 34
		0000 0010
		0010 0000
		0010 0010
练习:
	有一个整型变量a,要使a的第5bit保留,保持其他位取反,
		该如何操作,请写出表达式
	1101 1111 ==> ~32 a=a^~32;  a=a^(~(1<<5));
	
	结论:
		一个bit位与0进行“按位异或 ^"操作 保留原值
			x ^ 0 == x
		一个bit位与1进行“按位异或 ^”操作 结果取反
	        x ^ 1 == ~x
	
练习:
	交换两个整数a和b的值,不用临时变量
	a = a+b
	b = a-b //a+b-b a 
	a = a-b //a+b-a b
	
	a=a^b;
	b=b^a;
	a=a^b;
	如何证明?
	
	位运算只和当前位相关,因为它既然没有进位,也没有借位。
	值需要证明a b 是一个bit位的情况
	a    b   a=a^b     b=b^a      a=a^b   a    b
	1    1    0          1         1      1    1
	1    0    1          1         0      0    1
	0    1    1          0         1      1    0
	0    0    0          0         0      0    0
	
	<< 按位左移:双目运算符,按bit位整体往左移
		a<<n 把a按bit位整体往左移n位
		高位左移后,丢弃
		低位会空出n位,直接补0
		例子:
		1<<5
			0000 0000 0000 0000 0000 0000 0000 0001 <<5
			0000 0000 0000 0000 0000 0000 0010 0000

		如果左移后丢弃的高位都是0,那么左移n位,就表示在原值乘以2的n次方 
	
	>> 按位右移:双目运算符,按bit位整体往右移
		a>>n 把a按bit位整体往右移n位
		低位右移后,舍弃。
		高位会空出n位,补什么呢?
			对于无符号数,高位补0
			对于有符号位,高位补符号位
			
			“逻辑移位”
				无符号位的概念,逻辑左移也好,逻辑右移也罢
				都是补0
			
			“算术移位”
				有符号位的概念,算术右移后,高位补符号位
		练习:	
			a.分析如下程序的输出结果
			int a = -1;
			a = a>>31;
			printf("%d\n",a);//-1
			printf("%u\n",a);//2^32-1
				a:11111111 11111111 11111111 11111111
				a>>31 
				  11111111 11111111 11111111 11111111
			-----------------
			unsigned int a = -1;
			a = a>>31;
			printf("%d\n",a);//1
			printf("%u\n",a);//1
				a:11111111 11111111 11111111 11111111
				a>>31
				  00000000 00000000 00000000 00000001
			-----------------
			b.
			char a = -1;
			int b = a>>31;
			printf("%d\n",b);//-1
			printf("%u\n",b);//2^32-1
				//a:8bits
					1111 1111
				 a>>31
					把a>>31
					1111 1111
				a->b:短->长 短有符号数 高位补符号位
					11111111 11111111 11111111 11111111
				a->int:短->长
					11111111 11111111 11111111 11111111  >>31
				a>>31
					11111111 11111111 11111111 11111111
			------------------
			unsigned char a = -1u;
			int b = a>>31;
			printf("%d\n",b);//0
			printf("%u\n",b);//0
				//a:8bits
					1111 1111
				  a->int  短->长
				  00000000 00000000 00000000 11111111
				  a>>31 a无符号 高位全部补0
				  00000000 00000000 00000000 00000000 
				  
	5)赋值运算符:双目运算符,结合性从右到左。
		优先级倒数第二,仅比逗号高。
		=
		a=x;
			把表达式x的值,赋值给a
			赋值运算符要求左边的操作数必须为一个
			可写的地址(左值)lvalue
			
			5=5;error
			2+3=5;error
			i++ = 6;error
		赋值表达式:由赋值运算符连接操作数的式子
		赋值表达式的值就是最后赋值给左边变量的那个值。
			b=a=c=6;
			==>把表达式c=6赋值给a
			==>在把a的值赋值给b
		复合赋值运算符:
			赋值运算符可以和算术运算符 位运算符组成
			复合赋值运算符
			+= -= %= *= /=
			<<= >>= |= &= ^= 
			
		例子:
			a += 5;
				<==> a=a+5;
			a += 5+6;
				<==> a=a+(5+6);
			abc += 6;
				abc = abc+6;
			
	(6)条件运算符
		?:三目运算符 结合性是从右到左的
		expression?a:b 
			上面是一个条件表达式
			如果表达式expression的值为真,则整个表达式的值为a
			如果表达式expression的值为假,则整个表达式的值为b
			
			a = 5>4?1:0;
			
			"惰性”
	
	(7)逗号运算符:双目运算符,优先级是最低的,结合性从左到右
		表达式1,表达式2
		逗号表达式的值求值顺序:先求表达式1的值,然后再求表达式2的值
		整个逗号表达式的值表达式2的值
		例子:
		int a=5,b=6;
		a=(a=6,a+b);
		
		a=6,a=7,a=9.....
		逗号表达式扩展形式:
		表达式1,表达式2,表达式3,....表达式n
		求值顺序是,先求表达式1的值,然后再求表达式2的值,然后
		.....最后求表达式n的值
		整个逗号表达式的值表达式n的值
		
	(8)指针运算符
		*
		&
	
	(9)求字节运算符 sizeof
			单目运算符,求一个对象或类型所占的空间的字节数
			sizeof(x)
			sizeof 不要求x存在,但是要求x的类型是确定的
			因为只要你的类型是确定的,那么我就可以知道你所占内存大小。
			
			sizeof(int) == 4
			int a[10];
			sizeof(a[100])== 4
			
			sizeof(1) == 4
				==>typeof(x)
				==>sizeof(typeof(x))
			
			sizeof(1) == 4
				==>typeof(1) ==> int 
				==>sizeof(typeof(x)) ==> sizeof(int) ==> 4
				
			sizeof(1.0) == 8
			
			int a;
			sizeof(a+1) == 4
			sizeof(a+1.0) == 8
			
	(10)分量运算符
		求结构体的成员变量(分量)
		.
		->
	(11)下标运算符
	    []
		int a[10];
		a[0] a[1]
	(12)强制转换运算符
		(类型)
		如:
			(unsigned char)255
	(13)其他
	
	表达式
	什么是表达式呢?
		表达式就是表达某个意思的式子
		在C语言中,表达式一般是指用运算符连接起来的式子。
		是表达式就一定会有一个值,这个值就是上面表达式表达的“某个意思”
		
		如:
			I LOVE YOU 
			NB
			SB
			2B
			250
		
作业:
	1.取整型变量x中第p位开始n个bit位
	如: 0011 xxxx 0110 1111 取出 xxxx ==> 0000 0000 0000 xxxx
		
	2.将x中第p位开始的n个bit位设置为y(整数变量)中的
	最右边的n位的值,x的其余各位保持不变
	
	3.将x中的第p位开始的n个bit位取反,其余位保持不变
	
	4.实现循环移位
	1)将x循环右移n位
	(x<<(sizeof(x)*8-n))|((unsigned)x>>n)
	2)将x循环左移n位
	(x<<n)|((unsigned)x>>(sizeof(x)*8-n))
	
	5.分析如下程序的输出结果
	char c=-56>>30;
	printf("%d\n",c);//-1
	printf("%u\n",c);//2^32-1
	-----------------
	char c=-56u>>30;
	printf("%d\n",c);//3
	printf("%u\n",c);//3
		-56
	11111111 11111111 11111111 11001000	<--- -56在计算机中存放的形式
	带u 就是把上面的当作是unsigned 处理
	
	typeof(-56) ->int 
	typeof(-56u) -> unsigned int 
	
	-56u >> 30
	00000000 00000000 00000000  00000011
	
	--->char
	00000011
	
	%d:短->长  c 有符号  
	00000000 00000000 00000000  00000011 ->3 1+2^1 = 3
	%u 短->长 c 有符号
	00000000 00000000 00000000  00000011 ->3
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值