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

前言

今天给大家分享一下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//由于左右两边都是整数型,所以打印出3a = 2, b = 7;c = a / b;printf("%d ", c);//此时打印出来的结果是0return 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.3return 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//而%输出的结果为余数,则为1return 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 00000011int b = -4;//-4的原码:10000000 00000000 00000000 00000100//-4的反码:11111111 11111111 11111111 11111011//-4的补码:11111111 11111111 11111111 11111100int c = a & b;//a和b的补码的二进制位进行运算//3的补码 :00000000 00000000 00000000 00000011//-4的补码:11111111 11111111 11111111 11111100//有0才为0,两个为1才为1//即为00000000 00000000 00000000 00000000printf("%d\n", c);return 0;

| : 按(二进制)位或

规则见下图

#include <stdio.h>
int main()
{int a = 3;//3的补码:00000000 00000000 00000000 00000011int b = -4;//-4的原码:10000000 00000000 00000000 00000100//-4的反码:11111111 11111111 11111111 11111011//-4的补码:11111111 11111111 11111111 11111100int 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 00000001printf("%d\n", c);return 0;
}

 

^: 按(二进制)位异或 

#include <stdio.h>
int main()
{int a = 3;//3的补码:00000000 00000000 00000000 00000011int b = -4;//-4的原码:10000000 00000000 00000000 00000100//-4的反码:11111111 11111111 11111111 11111011//-4的补码:11111111 11111111 11111111 11111100int 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 00000001printf("%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 00000001return 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;
elsemax=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 是结构体成员
结构体成员的定义方式与变量和数组的定义方式相同
结构体成员,只是不能初始化。

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

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

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/397009.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

虚拟dom-Diff算法

虚拟dom-Diff算法 vue2 diff算法在vue2中就是patch&#xff0c;通过新旧虚拟dom对比&#xff0c;找到最小变化然后进行dom操作 在页面首次渲染的时候会调用一次patch并创建新的vnode&#xff0c;不会进行深层次的比较&#xff0c;然后再组件中数据发生变化的时候&#xff0c;…

QT事件。

目录 事件 鼠标事件 mousePressEvnet mouseMoveEvent 事件过滤 定时器事件 事件 事件分配机制&#xff1a;当某个事件(鼠标、键盘)发生的时候&#xff0c;窗口就会收到这个事件&#xff0c;并且调用相应的事件处理函数&#xff0c;事件处理函数的命名都是以Event结尾的&…

总线学习6--I2C(EEPROM)

鉴于I2C的项目还是很多&#xff0c;所以又多做了一个试验。 1 环境说明 主控还是树莓派Pico。eeprom用的是之前买的AT24C02。 软件环境还是老朋友micropython。 接线是这样接的。 24C02 PinPico PinVCC3.3VGNDGNDSDAGP16SCLGP17 2 代码 代码如下&#xff1a; from machine …

[Python学习日记-5] Python中的注释

[Python学习日记-5] Python中的注释 简介 注释的示例和使用说明 代码注释原则 简介 随着学习的深入。用不了多久&#xff0c;你就可以写上千甚至上万行的复杂代码啦&#xff0c;有些代码你花了很久写出来&#xff0c;但过了些天再回去看&#xff0c;发现竟然看不懂了&#x…

【wsl】wsl + vscode 中使用 typora 打开 markdown 文件

vscode 连接好wsl 使用Open in External App 一个五星好评的插件Open in External App则可以在vscode中用typora打开md文件&#xff0c;不仅如此&#xff0c;还有设定其他应用打开相应的文件&#xff0c;比如chrome打开html。插件食用方法也比较简单&#xff0c;安装后&#…

Linux 软件编程学习第十一天

1.管道&#xff1a; 进程间通信最简单的形式 2.信号&#xff1a; 内核层和用户层通信的一种方式 1.信号类型&#xff1a; 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 1…

gitea docker 快捷安装部署

前言 在前一篇博文&#xff08;什么是 Gitea&#xff1f;&#xff09;中&#xff0c;我们详细介绍了gitea的功能特性&#xff0c;以及其与其它git服务器之间的特性多维度对比。 在本文中&#xff0c;我们将详细介绍gitea的快捷安装部署&#xff0c;docker方式&#xff01; 1…

Linux磁盘管理与文件系统(二):实用工具和命令、fdisk分区示例

文章目录 4、查看或管理磁盘分区-fdisk格式选项示例 4、示例&#xff1a;使用 fdisk 命令创建分区需求操作步骤 5、创建文件系统-mkfs格式常用选项示例创建其他类型的文件系统 6、创建文件系统-mkswap格式常用选项示例拓展&#xff1a;关闭和启用交换分区拓展&#xff1a;swap分…

Visual Studio Code搭建VUE开发环境

Vue.js 是一款易学易用&#xff0c;性能出色&#xff0c;适用场景丰富的 Web 前端框架。它基于标准 HTML、CSS 和 JavaScript 构建&#xff0c;提供容易上手的 API 和一流的文档。可以用来开启PC网页、移动端网页页面、小程序等等 实验环境 VS Code 1.88.1Node 20.16.0Vue3.2…

趋动科技联合超聚变,让超融合彻底释放算力潜能

近日&#xff0c;趋动科技联合超聚变推出基于FusionOne HCI超融合的AI算力资源池化解决方案。该方案基于业内领先的AI算力资源池化技术&#xff0c;实现智能调度、异构算力融合管理等功能&#xff0c;让客户能够低成本获取AI算力&#xff0c;便捷使用AI算力&#xff0c;加速AI业…

AI学习记录 - transformer的Embedding层

创作不易&#xff0c;免费的赞 前面有介绍了GPT2如何进行token化的过程&#xff0c;现在讲下transformer的Embedding层 Embedding层就是一个巨大的矩阵&#xff0c;边长分别是词汇表长度和词向量维度&#xff0c;矩阵里面的每一个数字都是一个随机初始化的&#xff0c;或者是…

TinyWebserver的复现与改进(1):服务器环境的搭建与测试

计划开一个新坑, 主要是复现qinguoyi/TinyWebServer项目&#xff0c;并且使用其它模块提升性能。 本文开发服务器配置&#xff1a;腾讯云轻量级服务器&#xff0c;CPU - 2核 内存 - 2GB&#xff0c;操作系统 Ubuntu Server 18.04.1 LTS 64bit 打开端口 需要打开服务器3306、80…

常见硬件工程师面试题(四)

大家好&#xff0c;我是山羊君Goat。 对于硬件工程师&#xff0c;学习的东西主要和电路硬件相关&#xff0c;所以在硬件工程师的面试中&#xff0c;对于经验是十分看重的&#xff0c;像PCB设计&#xff0c;电路设计原理&#xff0c;模拟电路&#xff0c;数字电路等等相关的知识…

DriftingBlues2靶机渗透测试

DriftingBlues2靶机 文章目录 DriftingBlues2靶机信息收集FTP渗透web渗透权限提升靶机总结 信息收集 nmap扫描得到21,22和80端口&#xff0c;其中21ftp协议可以使用匿名用户登录 使用目录扫描一下网站&#xff0c;得到了blog目录 FTP渗透 匿名用户登录进去&#xff0c;发现…

WPF篇(8)- Button按钮

1. 用法解析 Button因为继承了ButtonBase&#xff0c;而ButtonBase又继承了ContentControl&#xff0c;所以&#xff0c;Button可以通过设置Content属性来设置要显示的内容。例如 <Button Content"确定"/>我们使用Button的时机&#xff0c;通常是鼠标点击事件…

补录:day023-回溯法

40.组合II 给定一个候选人编号的集合 candidates 和一个目标数 target &#xff0c;找出 candidates 中所有可以使数字和为 target 的组合。 candidates 中的每个数字在每个组合中只能使用 一次 。 注意&#xff1a;解集不能包含重复的组合。 思路:组合题目二&#xff0c;这个题…

2024世界机器人大会将于8月21日至25日在京举行

2024年的世界机器人大会预定于8月21日至25日&#xff0c;在北京经济技术开发区的北人亦创国际会展中心隆重举办。 本届大会以“共育新质生产力 共享智能新未来”为核心主题&#xff0c;将汇聚来自全球超过300位的机器人行业专家、国际组织代表、杰出科学家以及企业家&#xff0…

【云原生】Prometheus Pushgateway使用详解

目录 一、前言 二、Pushgateway概述 2.1 什么是Pushgateway 2.1.1 Pushgateway在Prometheus中的位置 2.2 为什么需要Pushgateway 2.3 Pushgateway作用 2.4 Pushgateway 工作原理 2.5 Pushgateway 使用场景 2.6 Pushgateway 优缺点 三、Pushgateway 部署 3.1 二进制安…

ip透传及实例

IP 透传介绍 “IP 透传”&#xff08;IP Passthrough&#xff09;是一种网络配置方式&#xff0c;指的是将网络服务提供商分配给用户的公网 IP 地址直接传递或分配给用户设备&#xff0c;而不是经过网络地址转换&#xff08;NAT&#xff09;处理。 在传统的网络环境中&#xf…

HTML5+JavaScript绘制彩虹和云朵

HTML5JavaScript绘制彩虹和云朵 彩虹&#xff0c;简称虹&#xff0c;是气象中的一种光学现象&#xff0c;当太阳光照射到半空中的水滴&#xff0c;光线被折射及反射&#xff0c;在天空上形成拱形的七彩光谱&#xff0c;由外圈至内圈呈红、橙、黄、绿、蓝、靛、紫七种颜色。事实…