操作符详解(内含二进制与原、反、补码知识点)--还有超详细图解!一看就会!

前言

今天给大家分享一下C语言操作符的详解,但在此之前先铺垫一下二进制和进制转换原码、反码、补码的知识点,都有详细的图解,也希望这篇文章能对大家有所帮助,大家多多支持呀!

目录

前言

一、二进制和进制转换

1.    10进制转化为10进制

​2.    2进制转化为10进制 

​2.1  10进制转化为2进制

3.    2进制转8进制和16进制

3.1   2进制转8进制

 3.2   2进制转16进制

二、原码、反码、补码

三、操作符

1、算数操作符(+   -   *   /   %)

2.移位操作符(<<、>>)

3.位操作符(&、|、^、~)

例题:求一个整数存储在内存中的二进制中的1的个数

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

5.条件表达式

6.逗号表达式   (exp1, exp2, exp3, …expN)   

7.下标访问操作符

8.函数调用操作符

9.结构体成员访问操作符 



一、二进制和进制转换

我们所说的2进制、8进制、10进制、16进制就是数值的不同表现形式

eg:13的2进制:1101

     13的8进制:15

     13的10进制:13

     13的16进制:d

1.    10进制转化为10进制

eg:123

  • 从个位开始,依次为0次方、1次方、2次方,位数更多的话,依次类推。

2.    2进制转化为10进制 
  • 2进制是由(0~1)的数字组成
  • 10进制是由(0~9)的数字组成

eg:1101

  • 相比十进制转化为十进制,这次的底数变为2了
  • 先分别算每一项,加在一起,别忘记乘上所在位数对应的数字

2.1  10进制转化为2进制

eg:125

所得出的余数从下往上写就是转化完的二进制,为01111101,即1111101。

大家动手操作一下将它再转化为10进制!!!

注意:当数字比较小时,可以使用下图所示方法(很重要,一定要会)

 

 如果是22呢,就为10110了

3.    2进制转8进制和16进制
  • 8进制是由(0~7)的数字组成
  • 16进制较为特殊,是由(0~9)、(a~f)组成的
3.1   2进制转8进制


首先,将0~7的数字各自写成2进制,最多有3个二进制位,所以像2的二进制本身是0,需要将它写成010,这个换算方法在上一节标红的注意,很实用,望大家都能掌握,在上图我已经先列出来了,因为8进制的每一位是0~7的数字,所以只需列出7个即可。

然后从2进制序列中右边低位开始向左每3个2进制位会换算一个8进制位,剩余不够3个2进制位的直接换算。

如图是2进制的0110101,从最右边开始依次取三个

011:3

101:5

001:1

但是值得注意的是,换算后的153,需要写成0153 (0开头,才会被当做8进制 )

大家可以上机调试一下,153与0153是不同的,如下

 3.2   2进制转16进制

2进制转化为16进制与转化为8进制相同,是将0~9、a~f各自写成2进制,需要4个2进制位

eg:2进制的01101011

同时我也将二进制都列了出来,但是建议还是要动手算算。

所以转化为的结果为0x6b,相同的(16进制前要加上0x)

二、原码、反码、补码

  • 整数的二进制形式有三种:原码、反码、补码。
  • 有符号整数的三种表示方法均有符号位和数值位两部分,二进制序列中,最高的一位被当做符号位,剩余的都是数值位。
  • 即正数最高位显示0,负数最高位显示1。
  • 整数分为正整数与负整数。
  • 在正整数中:原码=反码=补码。
  • 在负整数中:
  1. 直接将数值按照正负数的形式翻译成二进制得到的就是原码
  2. 将原码的符号位不变,其他一次按位取反就是反码(1变成0,0变成1,符号位不变)
  3. 反码+1得到补码

例:a=3与a=-3; 

注意:逢二进一,如果反码尾数是101,则变成110

整数在内存中存储的是2进制的补码

为什么数据存放的是补码?
在计算机中,数值一律用补码来表示和存储。因为使用补码可以将符号位和数值域统一处理;同时,加法和减法也可以统一处理(CPU只有加法器)此外,补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路。

下图是分析的过程

三、操作符

1、算数操作符(+   -   *   /   %)

(1)+ 、 -、  *三项与数学上用法是相同的。
(2)/ 是除法运算符,分两种情况讨论。
第一种:'/'左右两边都是整型

#include <stdio.h>
int main()
{
	int a = 7, b = 2;
	int c = a / b;
	printf("%d ", c);
	//此时打印出来的结果为3
	//7除以2得出3余1
	//由于左右两边都是整数型,所以打印出3

	a = 2, b = 7;
	c = a / b;
	printf("%d ", c);
	//此时打印出来的结果是0
	return 0;
}

第二种:'/'两边有一边是浮点型
在除法运算中,只要有一个操作数是浮点数,就是浮点数的除法运算。

#include <stdio.h>
int main()
{
	double c = 7.0 / 2;
	printf(" %lf \n", c);
	//此时打印出来的结果为3.5,因为其中一方由7变成了7.0,也就是浮点型

	c = 2 / 7.0;
	printf(" %.1lf \n", c);
	//此时打印出来的结果是0.3
	return 0;
}


(3)%是取模操作符
注意:取模的对象不能为0,且不能为浮点型,必须为整数!

#include <stdio.h>
int main()
{
	int a, b, sum;
	scanf_s("%d %d", &a, &b);
	sum = a % b;
	printf("%d", sum);
	//若a=7 b=2  则sum=1
	//因为7/2=3......1
	//而%输出的结果为余数,则为1
	return 0;
}

2.移位操作符(<<、>>)

注意:移位操作符的操作数只能为整数

这里的移位表示移动的是二进制位

也就是说,移动的是存储在内存中的二进制位(补码

(1)<<是左移操作符

移位规则:左边丢弃,右边补0

#include <stdio.h>
int main()
{
	int a = 10;
	int b = a << 1;
	//10的补码为00000000 00000000 00000000 00001010
	//左边少一位,右边加一位即为0000000 00000000 00000000 000010100此时变为20,即b=20;
	printf("b=%d\n", b);
	printf("a=%d\n", a);
	return 0;
}

(2)>>是右移操作符 

移位规则:

逻辑右移:与左移相似(左边用0填充,右边丢弃

算术右移:左边用原该值的符号位填充,右边丢弃

注意:右移到底采用算术右移还是逻辑右移是取决于编译器的!通常采用的都是算术右移

#include <stdio.h>
int main()
{
	int a = -10;
	int b = a >> 1;
	//-10的原码为10000000 00000000 00000000 00001010
	//-10的反码为11111111 11111111 11111111 11110101
	//-10的补码为11111111 11111111 11111111 11110110
	//此时是右移操作符
	//即为11111111 11111111 11111111 11111011
	//反码10000000 00000000 00000000 00000100
	//原码10000000 00000000 00000000 00000101
	//即为-5
	//采用的是算术右移
	printf("b=%d\n", b);
	printf("a=%d\n", a);
	return 0;
}

注意:移位操作符不能移动负数位,a<<-1这是不行的。

3.位操作符(&、|、^、~)

&:按(二进制)位

规则见下图

#include <stdio.h>
int main()
{
	int a = 3;
	//3的补码:00000000 00000000 00000000 00000011
	int b = -4;
	//-4的原码:10000000 00000000 00000000 00000100
	//-4的反码:11111111 11111111 11111111 11111011
	//-4的补码:11111111 11111111 11111111 11111100
	int c = a & b;
	//a和b的补码的二进制位进行运算
    //3的补码 :00000000 00000000 00000000 00000011
	//-4的补码:11111111 11111111 11111111 11111100
    //有0才为0,两个为1才为1
	//即为00000000 00000000 00000000 00000000
	printf("%d\n", c);
	return 0;

| : 按(二进制)位或

规则见下图

#include <stdio.h>
int main()
{
	int a = 3;
	//3的补码:00000000 00000000 00000000 00000011
	int b = -4;
	//-4的原码:10000000 00000000 00000000 00000100
	//-4的反码:11111111 11111111 11111111 11111011
	//-4的补码:11111111 11111111 11111111 11111100
	int c = a | b;
	//a和b的补码的二进制位进行运算
    //3的补码 :00000000 00000000 00000000 00000011
	//-4的补码:11111111 11111111 11111111 11111100
    //只要有1就是1,两个同时为0才是0
	//即为11111111 11111111 1111111 11111111 
	//此时为补码,应该先变为反码
	//10000000 00000000 00000000 00000000
	//所以原码为10000000 00000000 00000000 00000001
	printf("%d\n", c);
	return 0;
}

 

^: 按(二进制)位异或 

#include <stdio.h>
int main()
{
	int a = 3;
	//3的补码:00000000 00000000 00000000 00000011
	int b = -4;
	//-4的原码:10000000 00000000 00000000 00000100
	//-4的反码:11111111 11111111 11111111 11111011
	//-4的补码:11111111 11111111 11111111 11111100
	int c = a ^ b;
	//a和b的补码的二进制位进行运算
    //3的补码 :00000000 00000000 00000000 00000011
	//-4的补码:11111111 11111111 11111111 11111100
    //对应的二进制位,相同为0,相异位1
	//而3与-4的补码对应下来全部相异,所以全为1
	//即为11111111 11111111 1111111 11111111 
	//此时为补码,应该先变为反码
	//10000000 00000000 00000000 00000000
	//所以原码为10000000 00000000 00000000 00000001
	printf("%d\n", c);
	return 0;
}

~按(二进制)位取反 

将补码取反即可

#include <stdio.h>
int main()
{
	int a = 0;
	printf("%d\n", ~a);
	//按(二进制)位取反
	//0的补码: 00000000 00000000 00000000 00000000
	//取反后变为11111111 11111111 11111111 11111111
	//换成原码为10000000 00000000 00000000 00000001
	return 0;
}
例题:求一个整数存储在内存中的二进制中的1的个数

第一种:

#include <stdio.h>
int count_bit_one( unsigned int n)
{
	int count = 0;
    while (n)
{
	if ((n % 2) == 1)
		count++;
	n = n / 2;
}
    return count;
}
int main()
{
	int num = 0;
	scanf_s("%d", &num);
	int ret = count_bit_one(num);
	printf("%d\n", ret);
	return 0;
}

第二种:

#include <stdio.h>
int count_bit_one(int n)
{
	int i = 0;
	int count = 0;
	for (i = 0; i < 32; i++)
	{
		if (((n >> i) & 1 )== 1)
		{
			count++;
		}
	}
    return count;
}
int main()
{
	int num = 0;
	scanf_s("%d", &num);
	int ret = count_bit_one(num);
	printf("%d\n", ret);
	return 0;
}

第三种,更为优化的方法 

#include <stdio.h>
int count_bit_one(int n)
{
	int i = 0;
	int count = 0;
	while (n)
	{
		n = n & (n - 1);
		count++;
	}
    return count;
}
int main()
{
	int num = 0;
	scanf_s("%d", &num);
	int ret = count_bit_one(num);
	printf("%d\n", ret);
	return 0;
}

相比较于第二种方法,有几个1就算几次,更加方便,不用像第二种把32位都算一遍 

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

!                   逻辑反操作(把真变假,把假变真)
-                   负值
+                  正值
&                  取地址操作符

                    注:与按位与不同(a&b是按位与,&a是取地址)
sizeof           求的是变量(类型)所占空间的大小,单位是字节。
~                  对一个数的二进制按位取反
--                  前置、后置--
++                前置、后置++
*                   解引用操作符(在指针中会用到)
(类型)           强制类型转换

5.条件表达式

条件运算符也叫做三目运算符,需要接受三个操作数的,形式如下:

exp1?exp2:exp3

计算逻辑:exp1为真,exp2计算,结果为表达式结果

               exp1为假,exp3计算,结果为表达式结果

if(a>b)
  max=a;
else
  max=b; 


以上代码可以改写为

max=(a>b)?a:b;
6.逗号表达式   (exp1, exp2, exp3, …expN)   
#include <stdio.h>
int main()
{
	int a = 1;
	int b = 2;
	int c = (a > b,a=b+10,a,b=a+1)
	printf("%d\n", c);
	return 0;
}

c得出的值,不能直接算最后一项b=a+1进而得出结果为3,应该从左往右依次计算,因为前面表达式的结果,可能会影响后面的计算。

所以此题应该为13

同样的,逗号表达式也可以写在if语句中 

if(a=b+4,c=5/2,d>0)
7.下标访问操作符
#include <stdio.h>
int main()
{
	int arr[20] = { 1,2,3,4,5 };
	arr[3];//数组中下标为3的元素
	//[]是下标引用操作符
	return 0;
}

操作数是arr和3。 

8.函数调用操作符

 接受一个或多个操作数:第一个操作数是函数名,剩余的操作数就是传递给函数的参数。

#include <stdio.h>
int Add(int x, int y)
{
	return x + y;
}
int main()
{
	printf("hehe\n");//()是函数调用操作符,
	printf("%d\n", 100);
		int ret = Add(3, 5);//Add 3 5都是操作数
	return 0;
}
9.结构体成员访问操作符 
struct tag
{
  member1;
  member2;
} variable-list;


struct:结构体关键字
tag:结构体的标签名,可以自定义
struct tag:结构体类型
{}:里面放的是成员列表
variable-list:变量

 member1 , member2 是结构体成员
结构体成员的定义方式与变量和数组的定义方式相同
结构体成员,只是不能初始化。

这块结构体的内容后续会给大家补齐的,我还需要再沉淀沉淀,给大家展现一个完美的文章,嘿 

今天的分享就结束啦,后续我也会强化自己,补充这篇文章,把操作符更加详细的展示 

 

  • 12
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值