%%
# 纲要
> 主干纲要、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