当前位置: 首页 > news >正文

聊聊 C 里的进制转换、移位操作与算术转换

前言

学 C 语言时,总绕不开 “进制怎么转”“移位操作符怎么用”“表达式为啥这么算” 这些问题 —— 它们不算多高深,但都是写代码、调 Bug 的基础。

比如写个简单的位运算,若搞不清二进制和十进制的转换逻辑,很容易算错结果;处理表达式时,要是忽略了整型提升的规则,可能会碰到莫名其妙的运行错误。

这篇就整理了自己对进制转换、移位操作符、算数转换这些内容的理解,不求讲得多深,只希望把这些基础知识点理清楚,方便自己回头翻,也给刚入门的朋友做个参考。


目录

一、2进制与进制转换

1、2进制 —> 10进制

2、10进制 —> 2进制

3、2进制 —> 8进制

4、8进制 —> 2进制

5、2进制 —> 16进制

6、16进制 —> 2进制

【2进制、8进制、16进制转10进制总结】

二、原码、反码、补码

三、移位操作符

1、<< 左移操作符

2、>> 右移操作符

四、整型提升

五、算术转换

【整数类型参数表】


一、2进制与进制转换

咱日常说的 “二进制 / 八进制 / 十进制 / 十六进制”,其实就是数字的 “不同穿搭”—— 本质都是同一个数,换身衣服罢了~

比如数字 “15” 的 “穿搭秀”:

二进制款:1111(主打一个极简,就 0 和 1 俩元素)

八进制款:17(穿它得加个前缀0,不然认不出来)

十进制款:15(咱生活里最常穿的 “基础款”)

十六进制款:F(拽哥款,前缀得配0x才够范儿)

二进制的 “穿衣规则”别觉得它高冷,其实和十进制是 “亲戚”:

十进制:凑够 10 个就升级(满 10 进 1),元素是 0~9

二进制:凑够 2 个就跑路(满 2 进 1),元素只有 0 和 1

所以像1101这种 “01 串串”,就是二进制本进制啦~


1、2进制 —> 10进制

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

如下图:

10进制123每一位权重的理解
2进制和10进制是类似的,只不过2进制的每⼀位的权重,从右向左是:2^0 , 2^1 , 2^2 ...
如果是2进制的1101,该怎么理解呢?
2进制1101每一位的权重理解
你看,二进制1101这么一拆,每一位对应 “2 的次方面额”,乘完一加就得到 13 啦!所以二进制1101
转成十进制,就是咱们算出来的 13—— 这招 “按位拆算”,就是二进制转十进制的万能小妙招~

2、10进制 —> 2进制

这招主打一个 “拆了再拼”:把十进制数当成 “待拆分的大蛋糕”,每次用 2 除它,把剩下的 “余数小块” 记下来,直到除到 0 为止。

比如转 125:

  1. 拿 125÷2,商 62,余 1 → 记个 1
  2. 62÷2,商 31,余 0 → 记个 0
  3. 31÷2,商 15,余 1 → 记个 1……(就这么一直除,一直记余数)最后把记下来的余数从下往上倒着读,就是 1111101—— 这就是 125 对应的二进制啦!

简单说就是:除 2 取余,余数倒排,搞定~


3、2进制 —> 8进制

八进制的特点:每一位是 0~7,而 0~7 的数字转成二进制,最多只需要 3 位(比如 7 的二进制是 111)。

转换规则:从二进制的右边低位开始,每 3 位分为一组,每组转成对应的八进制数;不足 3 位的组直接换算。


4、8进制 —> 2进制

核心逻辑:八进制的每一位(0~7),刚好对应 “3 位二进制数”(比如八进制的 7 对应二进制 111),所以转的时候直接 “1 位八进制→3 位二进制” 展开就行。

操作步骤:

  1. 把八进制的每一位数字,单独转成对应的 3 位二进制数;
  2. 要是某一位转成二进制不足 3 位,就在左边补 0 凑够 3 位;
  3. 把所有位转好的二进制数连起来,就是最终结果。
8进制0153转2进制

5、2进制 —> 16进制

核心逻辑:十六进制每位是 0~9、a~f,这些数字转成二进制最多需要 4 位(比如 f 的二进制是 1111),因此转换时按 “4 位二进制→1 位十六进制” 分组即可。

转换规则:从二进制的右边低位开始,每 4 位分为一组,每组换算成对应的十六进制位;剩余不足 4 位的组直接换算。


6、16进制 —> 2进制

核心逻辑:十六进制的每一位(0~9、a~f),刚好对应 “4 位二进制数”(比如 16 进制的 f 对应二进制 1111),所以转的时候直接 “1 位 16 进制→4 位二进制” 展开即可。

操作步骤

  1. 把 16 进制的每一位数字 / 字母,单独转成对应的 4 位二进制数;
  2. 若某一位转成二进制不足 4 位,在左边补 0 凑够 4 位;
  3. 将所有位转好的二进制数连起来,就是最终结果。

    核心逻辑:十六进制的每一位(0~9、a~f),刚好对应 “4 位二进制数”(比如 16 进制的 f 对应二进制 1111),所以转的时候直接 “1 位 16 进制→4 位二进制” 展开即可。

16进制0xA3转2进制

【2进制、8进制、16进制转10进制总结】

进制转换类型基数位权规则(从右往左,第 k 位)核心计算方式
二进制→十进制22^(k-1)每位 ×2ⁿ 相加
八进制→十进制88^(k-1)每位 ×8ⁿ 相加
十六进制→十进制1616^(k-1)每位 ×16ⁿ 相加

二、原码、反码、补码

整数(有符号整型才用原反补表示)的二进制表示有三种方式:原码、反码、补码。

【通用规则】

有符号整数的这三种表示,都分成符号位数值位两部分:

  • 二进制的最高位是符号位:0代表 “正”,1代表 “负”;
  • 剩下的位是数值位,用来表示具体数值。

【正整数的表示】

正整数的原码、反码、补码完全一样,直接把数值转成二进制,最高位补0(表示正数)就行。比如 + 5(假设是 8 位):

  • 原码 / 反码 / 补码:0000 0101

【负整数的表示】

负整数的原、反、补码各不相同,得按步骤转换:

  1. 原码:把数值转成二进制,最高位补1(表示负数)。比如 - 5(8 位):1000 0101

  2. 反码:原码的符号位不变,数值位按位取反(0 变 1,1 变 0)。比如 - 5 的反码:1111 1010(符号位1不变,数值位000 0101取反成111 1010

  3. 补码:反码的基础上加 1。比如 - 5 的补码:1111 1011(反码1111 1010+1 =1111 1011

【补码转原码】

如果已知补码,想转原码,步骤是:补码按位取反,然后加 1(和 “原码转补码” 的操作一样)。比如补码1111 1011(对应 - 5):

  • 取反:1000 0100
  • 加 1:1000 0101(刚好是 - 5 的原码)

计算机里所有有符号整数的运算(不管是加还是减),全程都是用补码来算的

这是因为 CPU 硬件只有加法器,而补码能把减法 “伪装” 成加法 —— 比如算3-2,实际会变成3 + (-2的补码),用加法就能得到正确结果。

显而易见,用补码计算的结果是正确的 —— 不过这只针对有符号整数;如果是无符号整数,直接用二进制数值计算即可。

三、移位操作符

1、<< 左移操作符

移位规则:左边抛弃、右边补0

左移操作符演示

2、>> 右移操作符

移位规则:⾸先右移运算分两种:
  1. 逻辑右移:左边⽤0填充,右边丢弃
  2. 算术右移:左边⽤原该值的符号位填充,右边丢弃
逻辑右移演示
算术右移演示

通过在 VS 中的实际运行结果可以看出,C 语言中带符号整数的右移操作符(>>),底层遵循的是算术右移规则。

警告⚠️:对于移位运算符,不要移动负数位,这个是标准未定义的。
int num = 10; num>>-1;//error

四、整型提升

关于整型提升,其实是 C 语言里小整型参与运算的 “隐形规则”—— 因为 CPU 的整型运算器默认是int长度,所以charshort这类比int短的类型,在做加减、位运算前,都会先转成int(或unsigned int),这个过程就叫整型提升。

它的核心逻辑很简单:

1、有符号整数提升是按照变量的数据类型的符号位来提升的

2、⽆符号整数提升,⾼位补0
整型提升演示

注意,提升只是运算时的临时转换,运算结束后如果存回小整型变量,结果会被截断回原类型的长度。

五、算术转换

当运算符的两个操作数类型不同时,不能直接运算 —— 得先把类型 “等级低” 的那个,转换成 “等级高” 的类型,这个转换规则就是 “寻常算术转换”。

它的核心是一个 “类型优先级层级表”(等级越靠前,优先级越高):

long double double float unsigned long int long int unsigned int int

转换逻辑很简单:

看两个操作数的类型在层级表里的位置 ——把 “排名靠后”(优先级低)的类型,转换成 “排名靠前”(优先级高)的类型,然后再运算。

总结:

算术转换的目的是 “让不同类型的操作数统一成同一种高优先级类型”,避免运算出错 —— 本质是按 “类型优先级” 向上对齐。

【整数类型参数表】

类型分类位数 (bit)取值范围(十进制)最大值公式
无符号整数80 ~ 2552^8 - 1
160 ~ 655352^16 - 1
320 ~ 42949672952^32 - 1
640 ~ 184467440737095516152^64 - 1
有符号整数(补码)8-128 ~ 1272^7 - 1
16-32768 ~ 327672^15 - 1
32-2147483648 ~ 21474836472^31 - 1
64-9223372036854775808 ~ 92233720368547758072^63 - 1

核心规则:

无符号整数:n 位全部用于表示数值,取值范围是 0 ~ 2^n - 1(无符号位)。

有符号整数(补码):最高位是符号位(1 表示负数,0 表示正数),取值范围是 -2^(n-1) ~ 2^(n-1) - 1 (比无符号少 1 位数值位)。

http://www.rkmt.cn/news/133240.html

相关文章:

  • Excalidraw自定义组件库搭建方法论
  • Excalidraw本地化部署成本 vs. 云服务性价比分析
  • Excalidraw如何应对极端网络延迟?乐观更新策略
  • Excalidraw能否用于电影分镜脚本绘制?正在探索
  • 【stm32】cmake脚本(一)
  • Excalidraw新增团队成员角色权限矩阵表
  • 28、高级线程同步技术深度解析
  • 29、多线程同步与进程间通信技术解析
  • 4、Windows系统文件与网络操作全指南
  • Excalidraw能否用于航空航天系统设计?高可靠性验证中
  • Excalidraw镜像支持多租户隔离,SaaS模式可行
  • Excalidraw新增最近编辑者标记,协作责任明确
  • Excalidraw支持自定义快捷键映射,操作更顺手
  • Excalidraw如何实现断网续传?同步机制深入解析
  • Excalidraw镜像提供详细的使用行为分析报告
  • Excalidraw被多家咨询公司用于客户方案呈现
  • Excalidraw在文化遗产数字化保护中的创新应用
  • Excalidraw新增批量操作功能,选中即执行
  • 102302149赖翊煊综合实践
  • Excalidraw被多家独角兽公司采用的背后原因
  • 37、Windows 异步 I/O、完成端口与对象安全
  • 38、Windows 对象安全:UNIX 风格权限及相关操作详解
  • Excalidraw支持全局缩放,宏观微观自由切换
  • 39、深入探索Windows对象安全与代码可移植性
  • C++string: SBO 和 引用记数的写时拷贝
  • Excalidraw支持RTL语言布局,拓展中东市场
  • Excalidraw实战:绘制电商平台订单状态机图
  • Excalidraw镜像具备灾备恢复能力,业务连续性保障
  • Excalidraw镜像支持一键扩容,应对流量高峰
  • Excalidraw镜像提供用量统计报表,便于成本控制