C语言 操作符

       操作符分多种:算术操作符,移位操作符,位操作符,赋值操作符,单目操作符,关系操作符,逻辑操作符,条件操作符,逗号表达式,下标引用,函数调用和结构成员,表达式求值。 

算术操作符 

  • 加法(+):执行两个操作数的加法运算。
  • 减法(-):执行两个操作数的减法运算。
  • 乘法(*):执行两个操作数的乘法运算。
  • 除法(/):执行两个操作数的除法运算。如果两个操作数都是整数,则执行整数除法;如果包含浮点数,则执行浮点数除法。
  • 取余(%):获取两个整数操作数相除后的余数。

移位操作符

二进制中有三种表现式原码,反码,补码。内存中存储是补码且移位的也是补码。

     正数的原码,反码,补码是相同的
     例:正数(int整型占四个字节(32bit)。一个字节等于八个比特位)
     原码——00000000000000000000000000001010(10)
     反码——00000000000000000000000000001010(10)
     补码——00000000000000000000000000001010(10)
    
     负数的原码,反码,补码要经过计算的
     反码是符号位不变,其他位按位取反,就是反码。补码是反码+1  
     例:负数
     原码——10000000000000000000000000001010(10)
     反码——11111111111111111111111111110101
     补码——11111111111111111111111111110110

1.左移操作符(<<)

左边舍弃,右边补0。 

下面是正数时

int main()
{
	int a = 10;//a为正数时
	//00000000000000000000000000001010(a的补码)
	int b = a << 1;
	//00000000000000000000000000010100(b的补码)
	printf("a=%d\n", a);//10
	printf("b=%d\n", b);//20=a*2^1
	return 0;
 }

 负数时:

int main()
{
	int a = -10;//a为负数时
	//10000000000000000000000000001010(a的原码)
	//11111111111111111111111111110101(a的反码)
	//11111111111111111111111111110110(a的补码)
	int b = a << 1;
	//11111111111111111111111111101100(a左边舍弃右边补0即为b的补码)
	//10000000000000000000000000010011
	//10000000000000000000000000010100(b的原码)
	printf("a=%d\n", a);//-10
	printf("b=%d\n", b);//-20=a*2^1
	return 0;
}

2.右移操作符(>>)

 1.算术右移[平常见到](右边舍弃,左边补原来的符号位)
 2.逻辑右移                (右边舍弃,左边直接补0)

正数时:

int main()
{
	int a = 10;
	//00000000000000000000000000001010
	int b = a >> 1;
	//00000000000000000000000000000101(算术右移)
	//00000000000000000000000000000101(逻辑右移)
	printf("a=%d\n", a);
	printf("b=%d\n", b);
	return 0;
}

负数时:

int main()
{
	int a = -1;
	//10000000000000000000000000000001(a的原码)
	//11111111111111111111111111111110(a的反码)
	//11111111111111111111111111111111(a的补码)
	int b = a >> 1;
	//11111111111111111111111111111111(b的补码)
	//10000000000000000000000000000000
	//10000000000000000000000000000001(b的原码)
	printf("a=%d\n", a);
	printf("b=%d\n", b);
	return 0;
}

位操作符

1.按位与(&)

 对应二进制位有0为0,两个同为1为1。

int main()
{
	int a = 10;
	//00000000000000000000000000001010
	int b = -5;
	//10000000000000000000000000000101
	//01111111111111111111111111111010
	//01111111111111111111111111111011
	int c = a & b;
	//00000000000000000000000000001010(a)
	//01111111111111111111111111111011(b)
	//00000000000000000000000000001010(c)
	printf("c=%d\n", c);
	return 0;
}

2.按位或(|)

 对应二进制位有1为1,两个同为0为0。

int main()
{
	int a = 10;
	//00000000000000000000000000001010
	int b = -5;
	//01111111111111111111111111111011
	int c = a | b;
	//00000000000000000000000000001010(a)
	//01111111111111111111111111111011(b)
	//01111111111111111111111111111011(c)
	printf("c=%d\n", c);
	return 0;
}

3.按位异或(^)

对应二进制位相同为0,相异为1 。

int main()
{
	int a = -5;
	//01111111111111111111111111111011
	int b = 10;
	//00000000000000000000000000001010
	int c = a ^ b;
	//01111111111111111111111111111011
	//00000000000000000000000000001010
	//01111111111111111111111111110001
	printf("c=%d\n", c);//-15
	return 0;
}

 赋值操作符

  • 简单赋值(=):将右侧操作数的值赋给左侧操作数。
  • 复合赋值:如+=、-=、*=、/=、%=、<<=、>>=、&=、|=、^=等,它们在赋值的同时执行相应的算术或位操作。 

 单目操作符 

  • 逻辑非(!):对操作数进行逻辑非操作,如果操作数为真(非零),则返回假(0);如果操作数为假(0),则返回真(1)。
  • 取地址(&):获取变量的地址。
  • 间接引用(*):通过指针访问其所指向的值。
  • 自增(++)自减(--):分别使操作数的值增加或减少1。它们有前置和后置两种形式,前置形式在操作数被使用之前执行增减操作,后置形式则在操作数被使用之后执行。
  • sizeof:计算操作数的类型长度(以字节为单位)。
  • ~:对一个数的二进制按位取反。
  • (类型):强制类型转换。

关系操作符

  • 相等(==):检查两个操作数是否相等。
  • 不等(!=):检查两个操作数是否不相等。
  • 大于(>)小于(<)大于等于(>=)小于等于(<=):分别用于比较两个操作数的大小关系。

逻辑操作符 

  • 逻辑与(&&):如果两个操作数都为真,则返回真;否则返回假。逻辑与具有短路特性,即如果第一个操作数为假,则不会评估第二个操作数。(见假即假)
  • 逻辑或(||):如果两个操作数中至少有一个为真,则返回真;否则返回假。逻辑或同样具有短路特性也就是第一个操作数为真,不会再计算后面的操作数。(见真即真)

条件操作符 

  • 条件(表达式1?表达式2:表达式3):也称为三目操作符,用于根据条件表达式的真假来选择两个表达式中的一个进行计算。

 逗号表达式

  • 逗号(,):用逗号隔开的多个表达式从左向右依次执行,整个表达式的结果是最后一个表达式的结果。

 下标引用、函数调用和结构成员

  • 下标引用([ ]):用于访问数组的元素。
  • 成员访问(. 和 ->).(点操作符)用于访问结构体或联合类型的成员,->(箭头操作符)用于访问指向结构体或联合类型的指针的成员。

表达式求值 

       表达式求值的顺序一部分是由操作符的优先级和结合性决定,有些表达式的操作数在求值的过程中可能需要转换为其他类型。

截断:在实际表示中(比如在内存中),二进制数的开头可能不会有前导零(除非是为了对齐或特定格式的要求)。

  • 隐式类型转换:C的整型算术运算总是至少以缺省整型类型的精度来进行的。 为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换称为整型提升

 

int main()
{
	char ch1 = 24;
	//00000000000000000000000000011000
	//00011000 (取出一个字节即八个bit)————————截断
	//00000000000000000000000000011000一个字节中首位为符号位,则八个bit外剩下的bit全部补符号位
	char ch2 = 100;
	//00000000000000000000000001100100
	//01100100
	//00000000000000000000000001100100
	char ch = ch1 + ch2;
	//00000000000000000000000000011000 ch1——————整型提升
	//00000000000000000000000001100100 ch2
	//然后就是一位一位相加                64+32+16+8+4=124
	//00000000000000000000000001111100 (内存中为补码)
	
		//11111111111111111111111110000011 (先取反后加一)
		//11111111111111111111111110000100  原码

		//00000000000000000000000001111011 (先减一后取反)
		//11111111111111111111111110000100  原码

	//同样取一个字节10000100
	//11111111111111111111111110000100 (补码)
	//11111111111111111111111110000011
	//00000000000000000000000001111100  ch原码————————124
	printf("%d\n", ch);
	return 0;
}

 下面例举有符号char类型的取值范围的由来。之所以八个bit位因为char的字节为一(一个字节等于八个bit位),相同如果需要计算short的取值范围则需要16个bit位(两个字节),int则需要32个bit位(四个字节)等等。无符号的更简单一些,首位不是符号位而是有效位。

  • 算术转换 :如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数的转换为另一个操作数的类 型,否则操作就无法进行。下面的层次体系称为寻常算术转换。

 

  • 操作符的属性 :复杂表达式的求值有三个影响的因素。 1. 操作符的优先级 2. 操作符的结合性 3. 是否控制求值顺序。(相邻两个操作符才有优先级)

写表达式时尽量不要写的模棱两可(即问题代码),能简单写简单写。 

  • 30
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 18
    评论
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值