(学习笔记)2.2 整数表示(2.2.6 扩展一个数字的位表示)

文章目录


线索栏

  1. 将一个较小的整数类型转换为较大的类型时,无符号数和有符号数(补码) 分别采用什么方法?
  2. 零扩展和符号扩展的具体操作是什么?它们的数学原理(转换公式)是什么?
  3. 示例代码中,short sx = -12345和 unsigned short usx = sx在内存中的位模式相同吗?为什么?
  4. 当将它们分别转换为 int和 unsigned后(x和ux),输出的字节序列有何不同?这说明了什么?
  5. C语言标准对于类型转换顺序(改变大小 vs. 改变有符号性)有何规定?
  6. (练习题2.23)移位操作 (word << 24) >> 24在有符号和无符号语境下(fun1vs fun2)有何本质区别?

笔记栏

1. 核心概念:零扩展 vs. 符号扩展

1)目标

在不同字长的整数间转换,保持数值不变。

2)无符号数 → 更大类型(零扩展)

在二进制表示的高位(左侧)添加0。

(1)原理公式:若 u ⃗ = [ u w − 1 , ⋯ , u 0 ] \vec{u}=[u_{w−1},⋯,u_0 ] u =[uw−1,⋯,u0], u ' ⃗ = [ 0 , ⋯ , 0 , u w − 1 , ⋯ , u 0 ] \vec{u'}=[0,⋯,0,u_{w−1} ,⋯,u_0] u' =[0,⋯,0,uw−1,⋯,u0],则 B 2 U w ( u ⃗ ) = B 2 U w ' ( u ' ⃗ ) B2U_w(\vec{u})=B2U_w'(\vec{u'}) B2Uw(u )=B2Uw'(u' )。

(2)直观理解:正数的二进制表示不会因高位补零而改变数值。

3)补码数 → 更大类型(符号扩展)

在二进制表示的高位(左侧)添加符号位(最高有效位的副本)。

(1)原理公式: x ⃗ = [ x w − 1 , ⋯ , x 0 ] \vec{x}=[x_{w−1},⋯,x_0 ] x =[xw−1,⋯,x0], x ' ⃗ = [ 0 , ⋯ , 0 , x w − 1 , ⋯ , u 0 ] \vec{x'}=[0,⋯,0,x_{w−1} ,⋯,u_0] x' =[0,⋯,0,xw−1,⋯,u0],则 B 2 U w ( x ⃗ ) = B 2 U w ' ( x ' ⃗ ) B2U_w(\vec{x})=B2U_w'(\vec{x'}) B2Uw(x )=B2Uw'(x' )。

(2)直观理解:为保持负数(符号位为1)的负权重不变,必须复制符号位填充新增高位。图2-20的条形图用颜色块(负权重)直观展示了这一原理。

(3)推导证明:通过归纳法证明扩展一位(w+1)保持数值不变。关键在于权重关系: − 2 w + 2 w − 1 = − 2 w − 1 −2^w+2^{w−1}=−2^{w−1} −2w+2w−1=−2w−1

2.代码示例与深度分析

c 复制代码
short sx = -12345;          /* 补码: 0xCFC7 */
unsigned short usx = sx;    /* 无符号: 0xCFC7 (53191) */
int x = sx;                 /* 符号扩展: 0xFFFFCFC7 (-12345) */
unsigned ux = usx;          /* 零扩展: 0x0000CFC7 (53191) */

(1)关键观察1:sx 和 usx 的16位位模式完全相同(均为 0xCFC7),但解释不同(-12345 vs 53191)。这再次验证了"位+上下文"。

(2)关键观察2:转换为32位后,x 的位模式为 0xFFFFCFC7(符号扩展),ux 的位模式为 0x0000CFC7(零扩展)。相同源位模式,因上下文(类型)不同,采用了完全不同的扩展方式,导致最终32位模式截然不同。

(3)重要规定(C标准):当同时涉及改变数据大小和有/无符号转换时,标准规定先改变大小(进行符号/零扩展),再改变有符号性。

(unsigned) sx 等价于 (unsigned) (int) sx(先符号扩展为int,再将结果解释为无符号数),而非 (unsigned) (unsigned short) sx。

3.练习题

练习题2.22

通过对公式(2.3)的直接计算,验证 [1011], [11011], [111011] 均为-5的补码表示(后者是前者的符号扩展)。

练习题2.23

分析:

fun1:参数 word 类型为 unsigned。(word << 24) >> 24 全程为无符号运算(逻辑右移),结果转换为 int。此操作实质是提取低8位,并零扩展至32位(但随后被解释为有符号数)。

fun2:(int) word 先将无符号数 word 强制转换为 int(保持位模式,重新解释)。<<24 和 >>24 均为有符号运算(算术右移)。此操作实质是提取低8位,并进行符号扩展至32位。


总结栏

本节核心是理解如何安全地将整数扩展为更大字长,关键在于符号性决定扩展规则:

  1. 两条铁律:
    (1)无符号数 → 零扩展(高位补0)。
    (2)补码数 → 符号扩展(高位补符号位副本)。
  2. 底层原理:扩展是为了在改变表示宽度的同时,保持数学值不变。符号扩展的归纳法推导严谨地证明了这一点。
  3. 转换顺序至关重要:C语言规定,混合转换时先改变大小(应用扩展规则),再处理有/无符号转换。忽略此顺序会导致程序行为与直觉相悖。
  4. 移位的双重语义:相同的C运算符(>>)在无符号和有符号语境下行为不同(逻辑右移 vs算术右移),这是理解fun1和fun2差异的关键。fun1实现零扩展提取字节,fun2实现符号扩展提取字节。

理解这些规则是进行安全类型转换、解析二进制数据(如网络封包、文件格式)以及编写可移植底层代码的基础。练习题2.23是对该知识点极佳的检验与应用。

相关推荐
weixin_440401692 小时前
Python数据分析(Series+DataFrame+部分运算+groupby)
开发语言·python·数据分析
别退2 小时前
brain
科技·学习
宇木灵2 小时前
C语言基础-八、结构体和共同(用)体
c语言·开发语言·数据结构·笔记·学习·算法
拳里剑气2 小时前
C++ 11
开发语言·c++·学习方法
孞㐑¥2 小时前
算法—穷举,爆搜,深搜,回溯,剪枝
开发语言·c++·经验分享·笔记·算法
Highcharts.js2 小时前
如何根据派生数据创建钟形曲线图表?highcharts正态分布曲线使用指南:从创建到设置一文搞定
开发语言·javascript·开发文档·正态分布·highcharts·图表类型·钟形图
宇木灵2 小时前
C语言基础-九、动态内存分配
c语言·开发语言·学习·算法
楼田莉子2 小时前
Linux网络学习:网络的基础概念
linux·运维·服务器·网络·c++·学习
im_AMBER2 小时前
Leetcode 126 两数之和 II - 输入有序数组 | 盛最多水的容器
数据结构·学习·算法·leetcode