操作符详解

1.原码,反码,补码。

正数的原码,反码,补码相等。eg:2的原,反,补码是00000000000000000000000000000010(2进制).

重点讲负数的

例如-2

原码:10000000000000000000000000000010.//最前面的是符号位,1是表示‘-’,如果是‘0’则是‘+’。

反码:1111111111111111111111111111111111101//符号位不变,其余的反过来(1—>0,0—>1)

补码:1111111111111111111111111111111111110//反码+1就是补码

2.位移操作符

左移操作符 <<

规则:右边用原来的符号位填充,左边丢弃。

在这里插入图片描述

左移操作符的效果是乘以2 eg:

int a=10;
int b=a<<1//b=20,如果a<<3,这b=10*2^3=80,以此类推。

右移操作符>>

规则:左边用原来的符号位填充,右边丢弃。

右移操作符的效果是除以2
在这里插入图片描述

int main()
{
	int a = -6;
	printf("%d", a >> 1);
	return 0;
}///输出‘-3’

补充知识

数据存放和计算在计算机中是以补码的形式,因为CPU只会加法

3.位移操作符:&,|,^,~

& 按(2进制)位与

规则:对应的二进制位只要有0,那么就改为0;全是1则改为1。

int main()
{
	int a = 3; int b = -5;
	printf("%d", (a & b));
	return 0;
}
//00000000000000000000000000000011  3的补码
//10000000000000000000000000000101  -5的原码
//11111111111111111111111111111010  -5的反码
//11111111111111111111111111111011  -5的补码

//00000000000000000000000000000011  3的补码
//11111111111111111111111111111011  -5的补码

//00000000000000000000000000000011  最终结果的补码(因为它是正的,所以不用转换,结果直接就是3).

| 按位或

规则:对应的二进制位只要有1,那么就改为1;全是0则改为0。

int main()
{
	int a = 3; int b = -5;
	printf("%d", (a | b));
	return 0;
}//

//00000000000000000000000000000011  3的补码
//11111111111111111111111111111011  -5的补码

//11111111111111111111111111111011  (最终补码的结果,因为它是负的,所以要通过取反,再加1转化为原码。)------->
//10000000000000000000000000000101   最终结果是-5.

^ 按位异或

规则:对应的二进制位只要相同就为0,不相同则为1.

两个相同的数按位异或的结果是0. 0与任何数按位异或的结果是 原来的数。 (a^a=0, 0^a=a)

int main()
{
	int a = 3; int b = -5;
	printf("%d", (a ^ b));
	return 0;
}//
//00000000000000000000000000000011  3的补码
//11111111111111111111111111111011  -5的补码

//11111111111111111111111111111000   最终结果 -8

~ 按位取反

规则:对所有的二进制位取反(包括符号位)

应用

1.交换两个数(不用创建临时变量)

int main()
{
	int a = 3; int b = 9;
	printf("交换前a=%d, b=%d\n", a, b);
	a = a ^ b;
	b = a ^ b;//相当于b=a^b^b;  b^b=0,a^0=a,即b=a.
	a = a ^ b;//相当于a^a^b,同理可得 a=b.
	printf("交换后 a=%d b=%d", a, b);
	return 0;
}

2.判断一个数的二进制位上有几个1

int main()
{
	int x = 0; scanf("%d", &x); int count = 0;
	for (int i = 0; i < 32; i++)
	{
		if (((x >> i) & 1) == 1)
			count++;
	}
	printf("%d", count);
	return 0;
}
3.将任意二进制改为1
int main()
{
	int a = 22;//00000000000000000000000000010110
	//把第四位改为1,其余的不变。
	//00000000000000000000000000010110
	//              |
	//00000000000000000000000000001000  (将1左移三位)
	//             =
	//00000000000000000000000000011110
	a = (a | (1 << 3)); printf("%d\n", a);
	//将a改变回来
	a = (a & (~(1 << 3))); printf("%d", a);
	return 0;
}

4.逗号表达式

它的最终结果与最后一个表达式有关。

int a = 1; int b = 3;
int c = (a++, a = 10 + b, b = 1 - a);//最终结果b=-12,所以c的值是-12。
printf("%d", c);
return 0;

int a=1;int b=2;int d=10;
int c=(a++,b=a+10,d=10)//d的最终结果是10

应用

	a = get_val();
	count_val(a);
	while (a > 0)
	{
		//……
		a = get_val();
		count_val(a);

	}//这样写有点繁琐,可以改成逗号表达式。  如下:

	while (a = get_val(), count_val(a), a > 0)
	{
		//……
	}

5.下标访问[],函数调用()


int a[5] = { 1,2,3,4,5 };
printf("%d", a[2]);//[]下标访问操作符,操作数:一个数组名+一个下标。
int add(int x,int y)
{
return x+y;
}
int main()
{
int ret=add(2,4);//()函数调用操作符,函数名add是是操作数,2,3也是操作数。
return 0;
}

6.单目操作符

( + - ++ – & ~ * type sizeof )//自行了解

7.结构体成员访问操作符。

直接访问 .

#include<stdio.h>
struct grade
{
	int Math;
	int English;
};
struct student
{
	char name;
	int age;
	int ID;
	grade G1;//嵌套结构体

}s1, s2, s3;//创建全局结构体变量
int main()
{
	student s4 = { 'jack',19,2024099,{121,120} };//初始化
	student s5;//创建局部结构体变量
	printf("%d\n", s4.age);//.结构体成员访问操作符
	printf("%d", s4.G1.English);
}

间接访问

待更新。

8. 操作符的属性

![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=F%3A%5C%E5%9B%BE%E7%89%87%5CCT-20250626223206.png&pos_id=img-JF5MpZyA-175100042532

先看优先级,如果优先级相同就去看结合性。

eg:1+1-1,+与-的优先级相同,但结合性从左到右,所以先+,后-。
在这里插入图片描述

表达式求值

整型提升

原理:表达式的整型运算要在CPU的相应运算器件内执行,CPU内整型运算器(ALU)的操作数的字节长度一般就是int的字节长度,同时也是CPU的通用寄存器的长度。

因此,即使两个char类型的相加,在CPU执行时实际上也要先转换为CPU内整型操作数的标准长度。 通用CPU(general - purpose CPU)是难以直接实现两个8比特字节直接相加运算(虽然机器指令中可能有这种字节相加指令)。所以,表达式中各种长度可能小于int长度的整型值,都必须先转换为int或unsigned int,然后才能送入CPU去执行运算。

规则:符号位是什么,提升就补什么。

int main()
{
	char a = 3;
	//提升之前,00000011(最高位符号位是0,及无符号,直接补0)
	//提升之后,00000000000000000000000000000011
	char b = 127;
	//提升之前,01111111
	//提升之后,00000000000000000000000001111111
	char c = a + b;
	//c里面存的是100000010(符号位是1,提升前面全补1)
	//提升之后,11111111111111111111111110000010
	// (再转换为原码)
	//10000000000000000000000011111110
	printf("%d", c);
}

算术转换

1.long double
2.double
3.float
4.unsigned long int
5.long int
6.unsigned int
7.int
//规则:向上转换
int a+double b//把int a转换为double a

易错点

表达式1

a*b+c*d+e*f;
//这种表达式有两种计算方式 1.* * * + +    2.* * + * +。大部分情况下可以得到预期结果,但是由于运算顺序不同,如果表达式之间的变量的值会相互影响,就会出错,所以尽量加()

表达式2

int c=4;c+ --c//问题出在左右两边c的值,到底是开始时两边都是4,还是开始时右边是4,--之后再得到左边的c=3?,两种算法j'g不同

d long int
5.long int
6.unsigned int
7.int
//规则:向上转换
int a+double b//把int a转换为double a


### 易错点

表达式1

```C
a*b+c*d+e*f;
//这种表达式有两种计算方式 1.* * * + +    2.* * + * +。大部分情况下可以得到预期结果,但是由于运算顺序不同,如果表达式之间的变量的值会相互影响,就会出错,所以尽量加()

表达式2

int c=4;c+ --c//问题出在左右两边c的值,到底是开始时两边都是4,还是开始时右边是4,--之后再得到左边的c=3?,两种算法j'g不同
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值