这里说一下C的强类型转换,也是C++的static_cast。
在小端的机器实验了一下,
从位数多的类型(例如int64)转到位数少的类型(例如int32)是直接截取的,
这种情形是十分简单明了的。
不过不同环境底层的策略可能不大一样。
而反过来,从位数少的到位数多的,就稍微复杂一点,
在我的实验环境中,例如从a到b,首先会判断a是不是有符号的,
如果a是无符号的,那直接一个内存拷贝完事,
否则会判断是否为负,然后用0或1填充b中的高位,不管b是否有符号。
如果涉及加减乘除等复杂运算的都转为有符号的,都转为有符号的吧。
因为无符号遇到负数就悲剧了,用有符号的,在数据范围内都不会出错。
这个转换情况繁多,有一点是不变的是:数据对应内存段的bit串是一样的。
实验代码
#include <iostream>
#include <iomanip>
using namespace std;
//CPU@E5520,g++4.1.2
//2.6.18Linux_x86_64
int main() {
//有符号整型之间的转换,从32到64正确!
int int0 = 1, int1 = 2;
long long t0 = int0 - int1;
cout << "t0 = " << t0 << endl;
//无符号做减法之后,理论上是个负数
//但转换时被认为是无符号的,高位也不用什么处理了
unsigned int uint0 = 1, uint1 = 2;
long long t1 = uint0 - uint1;
cout << "t1 = " << t1 << endl;
//在同数量位数下,例如都是32位的
//无符号与有符号的运算首先会转成无符号的
long long t2 = uint0 - int1;
cout << "t2 = " << t2 << endl;
long long x0 = -2134864623938L;
int x1 = x0;
unsigned int x2 = x0;
cout << setbase(16) << x0 << endl;
cout << setbase(16) << x1 << endl;
cout << setbase(16) << x2 << endl;
//y1虽为无符号直接,但还是根据y0的正负填充高位
int y0 = -1;
unsigned long long y1 = y0;
cout << setbase(10) << "y1 = " << y1 << endl;
return 0;
}
运行结果:
t0 = -1
t1 = 4294967295
t2 = 4294967295
fffffe0ef02706be
f02706be
f02706be
y1 = 18446744073709551615
好吧,强制转换,去掉const修饰作用是令人一件不愉快的事情。
因为程序失去了原有的const语义,所以即使用了cast_const强制转换,
也务必人肉保证对用户态const是有效的。