%% # 纲要 > 主干纲要、Hint/线索/路标 # Q&A #### 已明确 #### 待明确 > 当下仍存有的疑惑 **❓<font color="#c0504d"> 有什么问题?</font>** # Buffer ## 闪念 > sudden idea ## 候选资料 > Read it later %% # 不同位宽的数据类型间的转换 - **位扩展**:从**较小字长**的数据类型**转换为一个更大字长/位宽的数据类型**时发生; - **位截断**:从**较大字长**的数据类型**转换为一个较小字长/位宽的数据类型**时发生; <br> # 位扩展 Bit Extension 将一个数值从一个**较小字长**的数据类型**转换为一个更大字长/位宽的数据类型**时,将发生 **==位扩展==**: - **无符号数**的位扩展——**零扩展**,全**补 0**; - **有符号数**的位扩展——**符号扩展**,全**补符号位**; > [!important] 位扩展的方式与转换到的目标类型无关,只取决于==原类型==是无符号类型还是有符号类型 > > - **无符号数**转为更大字长的"**==有符号数==**"时,也是对二进制位进行 "**==零扩展==**",<br>然后再**按有符号数类型对位模式进行解释** > > > > > - **有符号数**转为更大字长的 "**==无符号数==**"时,也是对补码的二进制位进行 "==**符号扩展**==",<br>然后再**按无符号数类型对位模式进行解释**。 > #### 无符号数的位扩展 将一个==**无符号数**==转换为一个**更大的数据类型(更大字长/更多位宽)**,执行 "**==零扩展==**"(zero extension)——**在二进制表示的高位前补 0**。 ```cpp // 无符号整数转更大字长的数据类型: 零扩展, 高位前面补0 void zero_extension() { // 8->16位 unsigned char uc = 5; assert((unsigned short) uc == 5); assert((short) uc == 5); // 转为有符号数, 执行零扩展后按有符号类型解释 // 16->32位 unsigned short us = 7; assert((unsigned int) us == 7); assert((int) us == 7); // 转为有符号数, 执行零扩展后按有符号类型解释 } ``` #### 有符号数的位扩展 **将一个==有符号数==转换为一个更大的数据类型(更大字长/更多位宽)**,对其**补码表示**执行"**==符号扩展==**"(sign extension)——**在补码表示的高位前==补上符号位的值==**。 > [!note] 对于负数 $-b$,转换为更大位宽 $w'$ 的无符号整型后,得到的真值为 $b'_{补数_{w'}}=2^{w'} - b$ ```cpp // 有符号整数转更大字长的数据类型: 符号扩展, 高位前面补符号位 void sign_extension() { // 8->16位 signed char sc = -5; assert((short) sc == -5); assert((unsigned short) sc == 65531); // 转为无符号数, 执行符号扩展后按无符号类型解释. // 16->32位 short ss = -7; assert((int) ss == -7); assert((unsigned int) ss == 4294967289); // 转为无符号数, 执行符号扩展后按无符号类型解释 } ``` <br><br><br> # 位截断 Bit truncation 将一个数值从一个**较大字长**的数据类型**转换为一个较小字长/位宽的数据类型**时,将发生 **==位截断==**——**丢弃高位,而只保留低位**。 - 对于**无符号数** $x$:将一个 $w$ 位无符号 $x$ 整数截断为 $k$ 位($w>k$),则得到的结果为 $x'=x\mod2^{k}$; - 对于**有符号数**:不能从算术运算上直接计算截断结果,只能截断后**将剩余 $k$ 位再按补码解释**。 - 对于**有符号整数**,**截断导致可能符号位改变** <br><br> # 参考资料 # Footnotes