C语言 操作符详解 上

目录

前言

一、操作符

1.1 算术操作符

二进制和进制转换

2进制转10进制

10进制转2进制数字

2进制转8进制

2进制转16进制

原码、反码、补码

1.2 移位操作符

1.3 位操作符

1.4 单目操作符

1.5 逗号表达式

1.6 下标访问[]、函数调用()



前言

操作符又称为运算符。作为运算对象的变量或者常量称为操作数。C语言中的操作符可以分为算术运算符、关系运算符、逻辑运算符、位运算符等。


一、操作符

c语言中 操作符的分类

• 算术操作符: + 、- 、* 、/ 、%
• 移位操作符: << >>
• 位操作符: &  |  ^ `
• 赋值操作符: = 、+= 、 -= 、 *= 、 /= 、%= 、<<= 、>>= 、&= 、|= 、^=
• 单⽬操作符: !、++、--、&、*、+、-、~ 、sizeof、(类型)
• 关系操作符: > 、>= 、< 、<= 、 == 、 !=
• 逻辑操作符: && 、||
• 条件操作符: ? :
• 逗号表达式: ,
• 下标引⽤: []
• 函数调⽤: ()
• 结构成员访问: . 、->

接下来让我们来看看C语言中的操作符吧

1.1 算术操作符

+ -就是我们生活中常见的加减操作

a = 2;
b = 3
c = a+b;// c=3+2=5
d = a-b;// c=2-3=-1
*就是操作符两端的操作数相乘
a = 2;
b = 3;
c = a*b; //c=2x3=6

/与我们熟悉的除法有点不同

当两端都是整数时,返回值也是整数(省去小数部分)

得两端至少有一个浮点数时,则返回浮点数

a = 6;
b = 4;
printf("%d",a/b)  //结果为2

a = 6.0;
b = 4;
printf("%f",a/b) //结果为2.5000000

%是取余操作符,用来计算余数的

a = 6;
b = 4;
c = a%b; // 6/4商1余2 所以c=2;  

 在讲后面的移位操作符和位操作符前,我们先来了解一下⼆进制的和进制转换的知识

二进制和进制转换

其实我们经常能听到2进制、8进制、10进制、16进制这样的讲法,那是什么意思呢?其实2进制、8进制、10进制、16进制是数值的不同表示形式而已。
比如说15的各种进制表示:
15的2进制:1111
15的8进制:17
15的10进制:15
15的16进制:F

其中我们最熟悉的可能是十进制的了,其实在生活中我们也有很多进制。

比如说60分钟为1个小时,7天为一周,1024MB等于1G等等

上面这些例子都有一个共同点,就是逢多少进1,比如说逢60分钟进为1个小时,逢7天进为1周。

二进制也是这样的,逢二进1,比如说二进制中1 为001,2为001+001结果等于002,但是二进制逢二进1,所以往前进1变为010。

 ⼆进制的规则

2进制中满2进1
2进制的数字每⼀位都是0~1的数字组成

2进制转10进制

其实10进制的123表⽰的值是⼀百⼆⼗三,为什么是这个值呢?其实10进制的每⼀位是权重的,10进制的数字从右向左是个位、⼗位、百位....,分别每⼀位的权重是 10^1, 10^2 , 10^3 ...
如下图:
2进制的每⼀位也是有权重的,从右向左是: 2^0,2^1,2^3……
比如说 2进制的1101

10进制转2进制数字

10进制可以通过连除2来转换为二进制数,所得余数从最后往前就是二进制数字了

2进制转8进制

8进制的数字每⼀位是0~7的,0~7的数字,各⾃写成2进制,最多有3个2进制位就⾜够了,⽐如7的二进制是111,所以在2进制转8进制数的时候,从2进制序列中右边低位开始向左每3个2进制位会换算⼀个8进制位,剩余不够3个2进制位的直接换算。
如:2进制的01101011,换成8进制:0153,0开头的数字会被当做8进制。

2进制转16进制

16进制的数字每⼀位是0~9,a ~f 的,0~9,a ~f的数字,各自写成2进制,最多有4个2进制位就足够了,比如 f 的⼆进制是1111,所以在2进制转16进制数的时候,从2进制序列中右边低位开始向左每4个2进制位会换算⼀个16进制位,剩余不够4个2进制位的直接换算。
如:2进制的01101011,换成16进制:0x6b,16进制表⽰的时候前⾯加0x

原码、反码、补码

整数的2进制表⽰⽅法有三种,即原码反码补码
有符号整数的三种表示方法均有符号位和数值位两部分,2进制序列中,最高位的1位是被当做符号
位,剩余的都是数值位。
符号位都是用0表⽰“正”,用1表示“负”。
比如说3的二进制表示00000011,-3用二进制表示就是10000011其中最高位就是符号位。
正整数的原、反、补码都相同。比如说3的原码反码补码都是00000011
负整数的三种表示⽅法各不相同。比如说-3
原码:直接将数值按照正负数的形式翻译成⼆进制得到的就是原码。为10000011
反码:将原码的符号位不变,其他位依次按位取反就可以得到反码。为111111100
补码:反码+1就得到补码。为11111101
对于整形来说:数据存放内存中其实存放的是补码
因为 在计算机系统中,数值⼀律⽤补码来表⽰和存储。原因在于,使⽤补码,可以将符号位和数值域统⼀ 处理;同时,加法和减法也可以统⼀处理(CPU只有加法器)此外,补码与原码相互转换,其运算 过程是相同的,不需要额外的硬件电路。

1.2 移位操作符

<< 左移操作符
>> 右移操作符
注: 移位操作符的操作数只能是整数。
<< 左移操作符
移位规则:左边抛弃、右边补0
#include <stdio.h>
int main()
{
 int num = 10;
 int n = num<<1;
 printf("n= %d\n", n);
 printf("num= %d\n", num);
 return 0;
}

运行结果

//二进制表示
  00000000000000000000000000001010  //10
//左移操作
0 00000000000000000000000000010100 //20
//左边抛弃右边补零

图解

>> 右移操作符

移位规则:首先右移运算分两种:
1. 逻辑右移:左边用0填充,右边丢弃
2. 算术右移:左边用原该值的符号位填充,右边丢弃
#include <stdio.h>
int main()
{
 int num = 10;
 int n = num>>1;
 printf("n= %d\n", n);
 printf("num= %d\n", num);
 return 0;
}
逻辑右移:
算术右移:

注意:对于移位运算符,不要移动负数位,这个是标准未定义的。

1.3 位操作符

位操作符:&、|、^、~

注:他们的操作数必须是整数。

&按位与(有0为0,没0为1):

n = -3;//11111101 补码
m = 5;//00000101  补码

n & m = //00000101 补码
        //所以等于5       

|按位或者(有1为1,没1为0):

n = -3;//11111101 补码
m = 5;//00000101  补码

n | m = //11111101 补码
        //所以等于-3    

^按位异或(相同为0,不同为1):

n = -3;//11111101 补码
m = 5;//00000101  补码

n | m = //11111000 补码
        //所以等于-8    

~按位取反

n =  00000000;
~n = 11111111;//-1 

-1的补码就是11111111

下面我们来看看两道例题:

1.不能创建临时变量(第三个变量),实现两个数的交换。
这道题唯一的难点就是不能创建第三个变量,我们可以用上面操作符来完成
首先我们可以看看
a ^ a = 0;
a ^ 0 = a ;

这样我们就可以完成代码了:

int main() {
	int a, b = 0;
	scanf("%d%d", &a, &b);
	printf("a=%d,b=%d\n", a, b);

	a = a ^ b;  
	b = a ^ b;  //b=a^b^b=a
	a = a ^ b;  //a=a^b^a=b

	printf("a=%d,b=%d\n", a, b);
}

2.求⼀个整数存储在内存中的⼆进制中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;
}

但上述代码还存在一些问题:比如输入-1,结果却是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) )//把1一直左移,循环32次,如果该位置为1则按位余不为零
 count++; 
 }
 printf("⼆进制中1的个数 = %d\n",count);
 return 0;
}

现在我们来输入-1看看:

结果就对了,那还可不可以再简化呢?

方法三

#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;
}

num = num&(num-1)可以依次去掉num中的1。

1.4 单目操作符

单目操作符:!、++、--、&、*、+、-、~ 、sizeof、(类型)

单目操作符指的是只含有一个操作数。

在之前文章中有介绍,可以去前面看看。

1.5 逗号表达式

逗号表达式,就是⽤逗号隔开的多个表达式。
 exp1, exp2, exp3, …expN
逗号表达式,从左向右依次执⾏。整个表达式的结果是最后⼀个表达式的结果。
int a = 1;
int b = 2;
int c = (a>b, a=b+10, a, b=a+1);//逗号表达式
其中c为13                 c=b
a = get_val();
count_val(a);
while (a > 0)
{
 //业务处理
 a = get_val();
 count_val(a);
}
如果使⽤逗号表达式,改写:
while (a = get_val(), count_val(a), a>0)
{
 //业务处理
}

1.6 下标访问[]、函数调用()

下标访问[]
操作数:⼀个数组名 + ⼀个索引值
int arr[10]={1,2,3,4,5,6,7,8,9,10]
//arr[3] = 4;//[]下标访问

函数调用()

接受⼀个或者多个操作数:第⼀个操作数是函数名,剩余的操作数就是传递给函数的参数。
#include <stdio.h>
void test1()
{
 printf("hehe\n");
}
void test2(const char *str)
{
 printf("%s\n", str);
}
int main()
{
 test1(); //这⾥的()就是作为函数调⽤操作符。
 test2("hello bit.");//这⾥的()就是函数调⽤操作符。
 return 0;
}


总结

本文章,讲了一些常见的操作符和二进制的基本概念

希望对你有所帮助

  • 31
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值