在平时的学习中,总会遇到一些符号位扩展的问题,之前一直没弄清楚,现在重新找了相关资料,总结如下:
首先如果所取的类型值,溢出,会发生什么情况?
先讨论有符号类型,以char为例,因为char类型范围在-128-127;当char a=128会发生什么?因为a=127的补码为:01111111;则128二进制码为:10000000,转换过来就为-128,
有图,有真相:
#include<iostream>
using namespace std;
int main() {
char a = 128;
for (int i = 7; i >= 0; --i) {
cout << ((a >> i) & 1);
}
cout << endl;
cout << a - '0' + 48 << endl;
}
如果,超过了取值超过八个比特位,会怎么样?令 a=256,会怎么样呢?
int main() {
char a = 256;
for (int i = 7; i >= 0; --i) {
cout << ((a >> i) & 1);
}
cout << endl;
cout << a - '0' + 48 << endl;
}
因为256的二进制表示为:1 00000000;因此产生了截断,只保留了最起始的八位,从而在看对应的位数。
再来看无符号类型,会发生什么情况,入unsigned char a=-1;看看输出:
#include<iostream>
using namespace std;
int main() {
unsigned char b = -1;
for (int i = 7; i >= 0; --i) {
cout << ((b >> i) & 1);
}
cout << endl;
cout << b - '0' + 48 << endl;
}
可见,无符号和有符号差不多,在看看超过八位,会怎么样?
#include<iostream>
using namespace std;
int main() {
unsigned char b = 256;
for (int i = 7; i >= 0; --i) {
cout << ((b >> i) & 1);
}
cout << endl;
cout << b - '0' + 48 << endl;
}
可见,同样只保留其最低八位,看其具体值,至少具体的有符号和无符号类型转换,见下面分析。
一、短数据类型扩展为长数据类型
1、要扩展的短数据类型为有符号数
进行符号扩展,即短数据类型的符号位填充到长数据类型的高字节位(即比短数据类型多出的那一部分),保证扩展后的数值大小不变。
例如:char x=10001001; short y=x; 则y的值应为11111111 10001001;
char x=00001001 ; short y=x; 则y的值应为00000000 00001001;
2、要扩展的短数据类型为无符号数
进行零扩展,即用零来填充长数据类型的高字节位
例如: unsigned char x=10001001; short y=x; 则y的值应为00000000 10001001;
unsigned char x=00001001; short y=x; 则y的值应为00000000 00001001;
二、长数据类型缩减为短数据类型
如果长数据类型的高字节全为1或全为0,则会直接截取低字节赋给短数据类型;如果长数据类型的高字节不全为1或不全为0,则转会就会发生错误。
三、同一长度的数据类型中有符号数与无符号数的相互转化
直接将内存中的数据赋给要转化的类型,数值大小则会发生变化。另短类型扩展为长类型时,但短类型与长类型分属有符号数与无符号数时,则先按规则一进行类型的扩展,再按本规则直接将内存中的数值原封不动的赋给对方。
从 | 到 | 方法 |
char | short | 符号位扩展 |
char | long | 符号位扩展 |
char | unsigned char | 最高位失去符号位意义,变为数据位 |
char | unsigned short | 符号位扩展到short;然后从short转到 unsigned short |
char | unsigned long | 符号位扩展到long; 然后从long 转到unsigned long |
char | float | 符号位扩展到long; 然后从long 转到float |
char | double | 符号位扩展到long; 然后从long 转到double |
char | long double | 符号位扩展到long; 然后从long 转到long double |
short | char | 保留低位字节 |
short | long | 符号位扩展 |
short | unsigned char | 保留低位字节 |
short | unsigned short | 最高位失去符号位意义,变为数据位 |
short | unsigned long | 符号位扩展到long; 然后从long转到unsigned double |
short | float | 符号位扩展到long; 然后从long 转到float |
short | double | 符号位扩展到long; 然后从long 转到double |
short | long double | 符号位扩展到long; 然后从long 转到double |
long | char | 保留低位字节 |
long | short | 保留低位字节 |
long | unsigned char | 保留低位字节 |
long | unsigned short | 保留低位字节 |
long | unsigned long | 最高位失去符号位意义,变为数据位 |
long | Float | 使用单精度浮点数表示。可能丢失精度。 |
long | double | 使用双精度浮点数表示。可能丢失精度。 |
long | long double | 使用双精度浮点数表示。可能丢失精度。 |
无符号数的转换
从 | 到 | 方法 |
unsigned char | char | 最高位作为符号位 |
unsigned char | short | 0扩展 |
unsigned char | long | 0扩展 |
unsigned char | unsigned short | 0扩展 |
unsigned char | unsigned long | 0扩展 |
unsigned char | float | 转换到long; 再从 long 转换到float |
unsigned char | double | 转换到long; 再从 long 转换到double |
unsigned char | long double | 转换到long; 再从 long 转换到double |
unsigned short | char | 保留低位字节 |
unsigned short | short | 最高位作为符号位 |
unsigned short | long | 0扩展 |
unsigned short | unsigned char | 保留低位字节 |
unsigned short | unsigned long | 0扩展 |
unsigned short | float | 转换到long; 再从 long 转换到float |
unsigned short | double | 转换到long; 再从 long 转换到double |
unsigned short | long double | 转换到long; 再从 long 转换到double |
unsigned long | char | 保留低位字节 |
unsigned long | short | 保留低位字节 |
unsigned long | long | 最高位作为符号位 |
unsigned long | unsigned char | 保留低位字节 |
unsigned long | unsigned short | 保留低位字节 |
unsigned long | float | 转换到long; 再从 long 转换到float |
unsigned long | double | Convert directly to double |
unsigned long | long double | 转换到long; 再从 long 转换到double |