操作符详解(1)

1. 各种操作符的介绍。

2. 表达式求值

1 操作符分类:

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

2 算术操作符

+ - * / %

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

3移位操作符

 << 左移操作符
>> 右移操作符

注:移位操作符的操作数只能是整数。
3.1左移操作符
移位规则:
左边抛弃、右边补0
在这里插入图片描述
3.2 右移操作符
移位规则:
首先右移运算分两种:
3. 逻辑移位
左边用0填充,右边丢弃
4. 算术移位
左边用原该值的符号位填充,右边丢弃
在这里插入图片描述
在这里插入图片描述
警告⚠ :
对于移位运算符,不要移动负数位,这个是标准未定义的。

4位操作符

& //按位与,二进制相同位上全1为1,有0为0
| //按位或,二进制相同位上有1为1
^ //按位异或,二进制位上相同为0,不同为1
//注:他们的操作数必须是整数。

练习理解例1

#include <stdio.h>
int main()
{
 int num1 = 1;
 int num2 = 2;
 num1 & num2;
 num1 | num2;
 num1 ^ num2;
 return 0; }

输出:
在这里插入图片描述
原因解释:按位与,二进制相同位上全1为1,有0为0
00000000000000000000000000000001 //1的二进制存储表达式
00000000000000000000000000000010 //2的二进制存储表达式
输出
00000000000000000000000000000000 //0

按位或,二进制相同位上有1为1
00000000000000000000000000000001
00000000000000000000000000000010
输出
00000000000000000000000000000000

^ 按位异或,二进制位上相同为0,不同为1
00000000000000000000000000000001
00000000000000000000000000000010
输出
00000000000000000000000000000011

例2:不能创建临时变量,实现两个变量内容交换

#include <stdio.h>
int main()
{
 	int a = 10;
	 int b = 20;
 	a = a^b;
	 b = a^b;
	 a = a^b;
 	printf("a = %d b = %d\n", a, b);
 	return 0; 
}

在这里插入图片描述
原因解释:按位异或满足交换律
^ 按位异或,二进制位上相同为0,不同为1
所以b=a^b ^b=a;
a=a ^b ^a=b;
(不过此方法不建议平时采用,效率较低,可读性差,针对数据类型单一)

例3 编写代码实现:求一个整数存储在内存中的二进制中1的个数。

参考代码:
//方法1
#include <stdio.h>
int main()
{
	 int num  = 10;
 	int count=  0;//计数
 	while(num)
 	{
	 	if(num%2 == 1)
 		count++;
 		num = num/2;
 	}
 	printf("二进制中1的个数 = %d\n", count);
 return 0; 
 }

在这里插入图片描述
在这里插入图片描述
上述方法缺点很明显,只能针对自然数进行运算,不过整体逻辑也是进制转化的逻辑,所以虽然有局限性,但仍然值得借鉴。

//方法二
#include <stdio.h>
int main()
{
 	int num = -1;
	 int i = 0;
	 int count = 0;//计数
 	for(i=0; i<32; i++)
 	{
 		if( num & (1 << i) )
 		count++; 
 	}
 	printf("二进制中1的个数 = %d\n",count);
 	return 0; 
 	}
//思考还能不能更加优化

在这里插入图片描述
针对负数也能输出,整数范围内都能输出。
缺点分析,任意一个整数都遍历32位,并且移动次数(1+32)*16次,计算次数较多,效率较低

//方法二略微优化
#include<stdio.h>
int main()
{
	int a = 0;
	scanf("%d", &a);
	int count = 0;
	while (a != 0)
	{
		if ((a & 1) == 1)
		{
			count++;
		}
		a=a >> 1;
	}
	printf("一共有%d个1\n", count);
	return 0;

移动32次,每移动一次判断一次,移动次数减少

//方法3:
#include <stdio.h>
int main()
{
 	int num = -1;
	 int i = 0;
 	int count = 0;//计数
 	while(num)
 	{
 		count++;
 		num = num&(num-1);
 	}
 	printf("二进制中1的个数 = %d\n",count);
 	return 0; 
 }

运算逻辑简述
11111111111111111111111111111111 //-1的补码存储
11111111111111111111111111111110 //-1-1的二进制补码
11111111111111111111111111111100//-1-1-1的二进制补码
运算32次
00000000000000000000000000000000
此时循环结束。
num和num的按位与,有多少1运算多少次,效率大大提高

5. 赋值操作符

赋值操作符是一个很棒的操作符,他可以让你得到一个你之前不满意的值。也就是你可以给自己重新赋值。

int weight = 120;//体重
weight = 89;//不满意就赋值
double salary = 10000.0;
salary = 20000.0;//使用赋值操作符赋值。
赋值操作符可以连续使用,比如:
int a = 10;
int x = 0;
int y = 20; a = x = y+1;//连续赋值
这样的代码感觉怎么样?
那同样的语义,你看看:
x = y+1; a = x;
这样的写法是不是更加清晰爽朗而且易于调试。

复合赋值符、
+=、-=、*=、/=、%=、>>=、<<=、&=、|=、^=
这些运算符都可以写成复合的的效果
比如

int x = 10; 
x = x+10;
 x += 10;//复合赋值
//其他运算符一样的道理

6单目操作符

6.1 单目操作符介绍

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

代码演示

#include <stdio.h>
int main()
{
 int a = -10;
 int *p = NULL;
 printf("%d\n", !2);
 printf("%d\n", !0);
 a = -a;
 p = &a;
 printf("%d\n", sizeof(a));
 printf("%d\n", sizeof(int));
 return 0; }

在这里插入图片描述
非真为0,非假为1,整形变量大小为4个字节,int当然也是4
6.2 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;
 	 }
//问:
//(1)、(2)两个地方分别输出多少?
//(3)、(4)两个地方分别输出多少?

在这里插入图片描述
在这里插入图片描述
无论怎么修改,传过去int类型,大小是4
同理char
类型大小为1

//++和--运算符
//前置++和--
#include <stdio.h>
int main()
{
    int a = 10;
    int x = ++a;
     //先对a进行自增,然后对使用a,也就是表达式的值是a自增之后的值。x为11。
    int y = --a;
    //先对a进行自减,然后对使用a,也就是表达式的值是a自减之后的值。y为10;
    return 0; }
//后置++和--
#include <stdio.h>
int main()
{
    int a = 10;
    int x = a++;
    //先对a先使用,再增加,这样x的值是10;之后a变成11;
    int y = a--;
    //先对a先使用,再自减,这样y的值是11;之后a变成10;
    return 0; 
 }

通过上述代码我们可以清楚感觉到前置++和后置++的区别
总的来说前置运算符先自增自减后使用
后置运算符先使用,后自增自减。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值