关于操作符的那些事【c语言】

在这里插入图片描述

算术操作符

+ - * / %


  • 除了%操作符外的其他几个操作符可以作用于整数和浮点数
  • 对于/操作符如果两个操作数为整数,执行整数除法。只要出现浮点数除法就是浮点数除法。
  • %操作符的两个操作数必须为整数。返回的是整数之后的余数。

移位操作符

  • 移位操作符的操作数只能是整数
  • 左移操作符 <<

首先得知道移位是移动二进制。整数的二进制表现形式有三种:原码(按一个数的正负直接写出它的二进制表示形式得到的就是原码)反码(原码的符号位不变其他位按位取反)补码(反码加1)。正数的原码反码补码相同。内存中存的是补码的二进制, 屏幕上打印出来的是原码。 所以在参与移位的时候移动的都是补码。


原码(符号位不变其他按位取反)得到反码 反码加1得到补码
补码(符号位不变其他按位取反)得到反码 反码加1得到原码


int main()
 {
	 int a = 10;
	 int b = a << 1;
	 //00000000000000000000000000001010
	 return 0;
 }

左边丢弃右边补0 a<<1的结果是移动之后的效果 ,但是a不变

  • 右移操作符 >>
    • 算术右移 ( 一般见到都是算术右移)

    右边丢弃 左边补原来的符号位


在这里插入图片描述


  • 逻辑右移

右边丢弃左边直接补0

int main()
{ 
	int a = -1;
	int b = a >> 1;
	printf("%d\n", a); 
	printf("%d\n", b);

	return 0;
}

对于移位操作符 不要移动负数位 (未经定义)

位操作符 (操作数必须是整数)

  • 按位与 &

按二进制位于 对应的二进制位有0则为0 两个同时为1才为1

  • 按位或 |

按二进制位或 对应的二进制位有1则为1,两个同时为0才为0

  • 按位异或 ^

按二进制位异或 相同为0 ,相异为1


举个例子加深一下印象
题目:不能创建临时变量(第三个变量),实现两个数的交换

int main()
{
	int a = 10;
	int b = 20;
	a = a ^ b;  //1
	b = a ^ b;  //2
	a = a ^ b;  //3
	printf(" %d %d", a, b);

	return 0;

 }

关于异或操作符的一个结论:a^a=0 , 0 ^a =a 而且异或支持交换律 也就是说3 ^ 5 ^3 的结果就是 3 ^ 3 ^ 5 。但是异或也有缺点 : 可读性差 异或只能针对整数的交换 效率也不如使用临时变量的方法
关于上述代码解释: 第二个a ^b 就是 a ^ b ^b ,可以等价于a , 就相当与 b =a 第三个 a ^ b 就是 a ^ b ^ a 。用一下结论就等价于 b , 就相当于 a = b 自然就完成了 不用创建临时变量实现了 a b 的互换。

赋值操作符

复合赋值符

  • += -= *= %= >>= <<= &= |= ^=

单目操作符

!( 逻辑反操作符) 、 -(负值) 、 + (正值) 、 & ( 取地址)‘sizeof ( 操作数的类型长度)、~(对一个数的二进制按位取反)、-- (前置、后置–)、++(前置、后置++)、 *(解引用操作符) 、 (类型) (强制类型转换)


sizeof用于数据类型 必须用括号 sizeof(int ) sizeof用于变量 sizeof(var_name) 或者sizeof var_name 都行。带括号的更加普遍 大多数情况下都使用带括号的 这点和函数不同 所以sizeof并不是函数

~是所有位按位取反

int main()
{
	int a = 10;
	short s = 5;
	printf("%d\n", sizeof(s=a+3));
	printf("%d\n", s);
	return 0;
}

sizeof 内部的表达式是不参与计算的 里面的大小由操作数类型决定

#include <stdio.h>
void test1(int* arr)
{
 printf("%d\n", sizeof(arr));//(2)
}
void test2(char* ch)
{
 printf("%d\n", sizeof(ch));//(4)
}
int main()
{
 int arr[10] = {0};
 char ch[10] = {0};
 printf("%d\n", sizeof(arr));//(1)
 printf("%d\n", sizeof(ch));//(3)
 test1(arr);
 test2(ch);
 return 0;
}

sizeof(arr)计算的是整个整形数组的大小,单位是字节。10 乘4 = 40 。sizeof(ch)计算的是整个字符数组的大小 为10乘1=10。
第二个sizeof (arr) 实参是数组 数组传参本质上是传首元素地址,形参用指针接收,而指针的大小为4个字节(32位平台)第二个sizeof(ch)实参是数组,数组传参本质上是传首元素地址,这里就会有小伙伴会认为char 类型是一个字节 字符指针就为一个字节 ,但是字符指针也是指针 所以大小为4个字节(32位平台)。


  • a++ 、++a 、 a–、 --a的使用
#include <stdio.h>
int main()
{
	int a = 10;
	int b = a++;
	printf("%d\n", a);
	printf("%d\n", b);
	return 0;
}

上面的代码和下面的代码一表达的意思是一样的 a++ 表示先使用在++ 同理a- -也是一样的道理

//代码1#include <stdio.h>
int main()
{
	   int a = 10;
	   int b= a ;
	   a = a + 1;
	printf("%d\n", a);
	printf("%d\n", b);
	return 0;
}
//代码二
#include <stdio.h>	
 void test(int b)
{
	printf("%d\n", b);
	

 }
int main()
{
	int a = 10;
	test(a++);
	printf("%d\n", a);
	return 0;

}

不论是前置++还是后置++会带有副作用 会影响自身,也就是会改变原来的值 上代码!

int main()
{
	//1
	int a = 10;
	int b = ++a;//b=11 a=11

	//2
	int a = 10;
	int b = a + 1;//b=11 a=10

	return 0;
}

逻辑操作符

  • && 逻辑与 (并且)
  • || 逻辑或 (或者)

&& 左边为假 右边不计算 || 左边为真,右边不计算

条件操作符

语法
exp1 ? exp2 : exp3
表达式一 为 表达式二计算 表达式三不计算 结果为表达式二
表达式一为表达式二不计算 表达式三计算 结果为表达式三

逗号表达式

语法
exp1, exp2, exp3, …expN
从左至右依次执行 ,左边可能会影响右边的结果 最后一个逗号表达式最为整个表达式的结果

隐式类型转换

##截断操作

int main()
{
	     char a = 3;
		 char b = 127;
		 char c = a + b; 
		 printf("%d\n", c);
		 return 0;
}

字面常量 3 是不能储存进char 变量中 ,3 是个整数 ,整数所占内存空间是32个比特位 而char 所占内存空间为8个比特位 自然需要发生截断 。那这里就有小伙伴问了 有32位,只需要8位 截断哪里?截断的规则:把低位的字节数放置到需要截断储存的变量中
在这里插入图片描述

整形提升

整形提升的条件:只有当表达式中出现长度小于int类型的整形值,才需要整形提升,将其转换位int 类型或者 unsigned int类型
整形提升的规则: 对于有符号类型来说 ,整形提升是在高位补变量的符号位; 对于无符号类型的整形变量,直接高位补0就可以了
补充:
char 到底是signed char 还是unsigned char 是取决于编译器的,不过常见的编译器下,char 是signed char
short 默认是signed short
int默认是 signed int
long 默认是signed long


算术转换

那如果大于整形怎么办 ? 算术转换就用来处理这种情况。如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数的转换为另一个操作数的类
型,否则操作就无法进行。下面的层次体系称为寻常算术转换
long double
double
float
unsigned long int
long int
unsigned int
int
只能向上转换


下面讲一下上述代码的具体过程

a b 截断
00000000 00000000 00000000 00000011 --3
截断 留下 00000011
00000000 00000000 00000000 01111111 --127
截断 留下 01111111
分别整形提升
00000000 00000000 00000000 00000011
00000000 00000000 00000000 01111111
相加
00000000000000000000000010000010
截断 留下 10000010
在提升
11111111 11111111 11111111 10000010 (补码)内存中存储的是补码 ,打印在屏幕上的是原码
再进行转换
11111111111111111111111110000001
10000000000000000000000001111110 (原码)
从而得到结果 -126


在这里插入图片描述

如果你觉得这篇文章对你有帮助,不妨动动手指给点赞收藏加转发,给鄃鳕一个大大的关注
你们的每一次支持都将转化为我前进的动力!!!

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鄃鳕

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值