一、运算符
什么是运算符?
运算符就是表示某种运算操作的符号
+ - * / %

运算符的分类
按照操作数的个数,分为几目运算符
·单目运算符:~ ! ++ -- & *
·双目运算符:+ - * / = %
·三目运算符:? :
				int a = 3>4?1:2 a=2;
				
结合性:决定先算哪一个操作数的问题
+:从左到右(a+b:表示先算a,再算b)
	a+b和b+a 有区别
	int a=1,b=1;
	(a++)+(a+b) == 4
	(a+b)+(a++) == 3

优先级:
在含有多个运算符的表达式中,决定先算哪个运算符的问题
	1+2*3=7
	单目运算符>算数运算符>关系运算符>逻辑运算符>赋值运算符>逗号(,)运算符

表达式:表示某个值的式子,可以由单个的数字,也可以由运算符加上数字组成
while(1);
是表达式就一定会有一个值(表达式是一个常量),表达式最终肯定是要表达某个意思

其它分类:
1:算术运算符
	+ - * / %
	++:自增运算符
		自增(自己+1),单目运算符,要求操作数必须为左值,并且必须是一个整数(整型变量)
		
		int a = 0;
		a++;//可以
		
		5++;//不行
		
		(a+b)++;//不行,a+b是一个算数表达式,一定有一个确定的值,a+b不是一个变量
		
		char y;//y也是一个整型变量,并且有一个不确定的初值
		y++;//可以,更加不确定它的值了
		
		(a++)++;//不行,a++是一个表达式,有一个确定的值,是1
		
	后置自增:++在操作数的后面
			后置自增表达式的值就是操作数的值
			执行后置自增表达式之后,操作数的值+1
			
	前置自增:++在操作数的前面
			前置自增表达式的值是操作数的值+1
			执行前置自增表达式之后,操作数的值+1
			
		int a =0;
		a++;
		printf("%d\n",a++);
		printf("%d\n",a);
		
	--:自减运算符
	后置自减:--在操作数的后面
			后置自减表达式的值就是操作数的值
			执行后置自减表达式之后,操作数的值-1
			
	前置自减:--在操作数的前面
			前置自减表达式的值是操作数的值
			执行前置自减表达式之后,操作数的值-1
			
		int a = 0;
		printf("%d\n",--a);//-1
		printf("%d\n",a);//-1
	
2:关系运算符
用来判断两个东西的关系:“关系”就是数值大小的关系
如果关系成立:1
	  不成立:0
	  4>3>2;这个表达式的值是0;
	  4>3 ? 1
	  1>2 ? 0
	  4>3>0? 1
	> < == >= <= !=
	
3:逻辑运算符(真 非0,假 非1)
逻辑表达式里面只有真(1)和假(0)
	&& 与:双目运算符(有假则假)
			a && b
			真 && 假 :假
			假 && 假 :假
			真 && 真 :真
		怎么表示数学关系式:4>3>2?
				4>3 && 3>2
			
			
	|| 或:双目运算符(有真则真)
			a || b
			真 || 假 :真
			假 || 假 :假
			真 || 真 :真
		怎么表示数学关系式:4>3>2?
				4>3 && 3>2
	
	!  非:单目运算符(遇真则假,遇假则真)
			
			!真:假
			!假:真
			
			!4 == 0;
			4 :真
			
	用逻辑运算符表示闰年
		闰年:是4的倍数,但不是100的倍数
			  是400的倍数
			  两个条件满足其中一个即可
			  
			  怎么描述a年是闰年(逻辑真是闰年,逻辑假不是闰年) 
			  
			  (a%4 == 0 && a%100 != 0) || (a%400 == 0)
			  
	练习:
	int main()
	{
		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);
		return 0;
	}
	上述程序运行后,各个变量的值:
	a:1,b:2,c:3,d:4,m:0,n:1
	
	
		c语言的惰性运算
			“惰性运算”:能不算就不算
			&&左边表达式已经为0了,整个表达式就可以确认是0了,右边算不算就没关系了。

4:位运算符
位运算符是按照bit位展开来进行运算的,意思是说操作数要展开成bit位的形式(化成二进制),再进行运算
位运算符要求操作数必须是整数(兼容的整数类型)
	&:按位与
	|:按位或
	~:按位取反
	^:按位异或
	<<:按位左移
	>>:按位右移
		除了按位取反是单目运算符以外,其他都是双目运算符,结合性是从左到右
		
			什么是按bit位展开来进行运算?
				3 & 2 == ?
				3:011
					&
				2:010
			  3&2:010
		
		~(按位取反)和!(逻辑非)的区别
		
		char a = -3; 1101
		~a == 2;0010
		
		char a = -3;//非0就是真
		!a == 0;//非a为假(0)


		&(按位与)和&&(逻辑与)的区别
			3 & 2 == 2;
			3 && 2 == 1;(逻辑真)
			
		|(按位或)和||(逻辑或)的区别
			3 | 2 == 3;
			3 || 2 == 1;
			
			254 | 0 == 254;
			254 || 0 == 1;
			
			
结论:
在按位或的运算中,有1则1;
在按位与的运算中,有0则0;

练习:假设有一个整型变量a(char),要把a的第4bit位设置成0,其余bit位不变,怎么操作?
	a = a & 247; a = a &  ~(char)8;
	<==>
		char b = 8;
		a = a & (~b);
	
练习2:假设有一个整型变量a(int),要把a的第5bit位设置成1,其余bit位不变,怎么操作?
	a = a | 16;
		
结论:
按位与或者按位或运算中
			x & 1 == x;
				1 & 1 == 1;
				0 & 1 == 0;
			x | 0 == x;
				1 | 0 == 1;
				0 | 0 == 0;
				
	按位异或:^
		“异或”:“不同否?”
			相同为0,不同为1;
		
		x ^ 0 == x;
			0 ^ 0 == 0;
			1 ^ 0 == 1;
			
		x ^ 1 == ~x;
			0 ^ 1 = 1;
			1 ^ 1 = 0;
		
练习:假设有一个整型变量a(char),要把a的第5bit位保留,其余bit位取反,怎么操作?
		a = a ^ 239;
		
	
	  假设有一个整型变量a(char),要把a的第5bit位取反,其余bit位保留,怎么操作?
	  
		a = a ^ 16;
	
	
按位左移:<<
双目运算符,结合性从左往右,“把一个数按bit位整体左移”
a << n;//“把a按bit位整体左移n位”
高位左移后直接舍弃,低位就会空出来,直接补0



	int a = 9;
	printf("%d\n",a<<3);//72
		00000000 00000000 00000000 00001001
		00000000 00000000 00000000 01001000 左移3位
		
			如果左移之后,舍弃的高位都为0,那么a<<n的结果就是a*2^n
			
			
分析下面程序的输出结果:

		char a = (unsigned char)-1 << 2;
		printf("%d\n",a);//-4
		printf("%u\n",a);//2^32 - 4
		
			unsigned char(-1):
					1111 1111
				 11 1111 1100
				 a: 1111 1100
				 
					11111111 11111111 11111111 1111 1100
					
练习:构造一个整数,使它的第7bit为和第28bit位为1,其余bit位为0,怎么构造?(用一个表达式来描述)
		int
		((1<<21)++ )<<7
		0000 0000 0000 0000 0000 0000 0000 0001
		0000 0000 0001 0000 0000 0000 0000 0000
		0000 0000 0001 0000 0000 0000 0000 0001
		0000 1000 0000 0000 0000 0000 0100 0000
		
		(1<<7) | (1<<28)
		0000 0000 0000 0000 0000 0000 0100 0000
		0000 1000 0000 0000 0000 0000 0000 0000
		0000 1000 0000 0000 0000 0000 0100 0000
		
		
按位右移:>>
双目运算符,结合性从左往右,“把一个数按bit位整体右移n位”
a >> n;//“把a按bit位整体右移n位”
低位右移后直接舍弃,高位补什么?
·对于有符号数,高位补符号位
·对于无符号数,高位补0

如果右移之后,舍弃的低位都为0,那么a>>n的结果就是a/2^n
int a =250;
printf("%d\n",a>>3);//31
		1111 1010
		0001 1111:31
		
		
	练习:分析下面程序的输出结果:
	
	int main()
	{
		int a = -1;
		a= a >> 31;
		printf("%d\n",a);//-1
		printf("%u\n",a);//2^32-1
	}
	
	0000 0000 0000 0000 0000 0000 0000 0001
	1111 1111 1111 1111 1111 1111 1111 1111
	1111 1111 1111 1111 1111 1111 1111 1111
	
	
	int main()
	{
		unsigned int a = -1;//2^32-1
		a = a >> 31;
		printf("%d\n",a);//1
		printf("%u\n",a);//1
	}
	
	1111 1111 1111 1111 1111 1111 1111 1111
	0000 0000 0000 0000 0000 0000 0000 0001
	
	
	int main()
	{
		char a = -1;
		int b = a >> 31;
		printf("%d\n",b);//-1
		printf("%u\n",b);//2^32-1
	}
	
								  1111 1111
	1111 1111 1111 1111 1111 1111 1111 1111
	
	
	
	int main()
	{
		unsigned char a = -1;
		int b = a >> 31;
		printf("%d\n",b);//0
		printf("%u\n",b);//0
	}
	
			1111 1111
			0000 0000



掩码:
掩码是一个位模式,表示从一个字中选出的位的集合
掩码中为1的那些bit位,就是我们要选取的bit位的集合

例子:
	如果我们要选取第0bit和第1bit,则掩码为:0x3(11B)
	如掩码为0xff,表示我们要选取低8位
	
	如:
		假设有一个整型变量x = 0x345678AB;想要选取x的低8位,该如何操作?
		利用掩码:mask = 0xff
		x & mask ==> 0xAB;
		
			int x;
				x:00101010 00101010 00101010 00101010  &
			 0xff:00000000 00000000 00000000 11111111
			 
	假设有一个整型变量x,想要选取x的第5bit开始的第4个bit位,该如何操作?
	
		x:01001001 01001001 01001001 01001001
								   1 010	 
								   
		掩码:0xf << 5 或者111100000
		
		x & (0xf << 5)
					:00000000 00000000 00000001 01000000
					
		(x & (0xf << 5)) >> 5
					:00000000 00000000 00000000 00001010
					
					
赋值运算符(=)
注意区别关系运算符“==”

a = b,双目运算符,结合性从右至左,把表达式b的值,赋值给a;
赋值运算符的优先级排行倒数第二,倒数第一是逗号运算符

a必须是一个可写的地址"左值""变量"
	例子:
		5 = 5;//×
		2 + 3 = 5;//×,2+3是一个常量
		2 + 3 == 5;//√,表达式的值为1
		x + y = 5;//×,x+y是表达式,有确定的值
		x++ = 5;//×,x++是一个表达式
		y = x = 5;//√
			赋值表达式的值:就是赋值完成之后左边的那个操作数的值
			
				int a = 1;
					表达式a = 2;的值是2
					表达式a == 2的值是0
					

复合赋值运算符:
+= ,-=, *=, /=, %=, <<=, >>=, |=, &=, ^=
a+=1 <==> a = a+1;
a|=2 <==> a = a|2;

条件运算符:
?:"三目运算符"
表达式?表达式2:表达式3
整个表达式“表达式?表达式2:表达式3”的结果
	表达式1为真"非0",结果就是表达式2
	表达式1为假"0",结果就是表达式3
	
	int a = 1==2?3:4;
	printf("%d\n",a);//4
	
	int a,b;
	a = b=2?3:4;
	printf("%d\n",a);//3
	
逗号运算符:
a,b		双目运算符,结合性从左至右,优先级最低
		例如:
			a = (1,2);
			上面是一个逗号表达式:把表达式"1,2"的值赋值给a;
			
			a = 2,a = 3;
			也是一个逗号表达式;
			
	逗号表达式的形式可以是下面这样的:
		表达式1,表达式2,表达式3,······,表达式n;
		求值顺序:先计算表达式1的值,再计算表达式2的值,依次下去,最后计算表达式n的值。
		最后整个表达式的值,就是最右边那个表达式的值;
		
		int a,b=0;
		printf("%d\n",(a++,++b,b++));//1
				为什么是1?
					执行表达式1:表达式"a++"的值是0;a的值是1
					执行表达式2:表达式"++b"的值是1;b的值是1
					执行表达式1:表达式"b++"的值是1,b的值是2
					
指针运算符:
	*:指向运算符
	&:取地址符
		见之后指针专题
		
求字节运算符
	sizeof();
	
分量运算符:
	·
	->
		见之后结构体专题
		
下标运算符
	[]:取数组的下标
		见之后数组专题
		
强制类型转换运算符
	(int)3.5 ==> 3
	
其他未分类:………………

	运算符的优先级和结合性总结:
		优先级排行:
			() [] -> ·
			! ~ ++ -- +(正号) -(负号) * &     (从右至左)
			+ - * / ...
			<< >>
			< <= > >= == !=
			& | ^ && ||
			? :
			= += -= *= /=(从右至左)
			,
		结合性:除了标明从右至左的,其他结合性全是从左至右。


逸一时,误一世