隐式类型转换
在下面这些情况下,编译器会自动地转换运算对象的类型:
1. 在大多数表达式中,比int类型小的整型值首先提升为较大的整数类型。
2. 在条件中,非布尔值转换成布尔类型。
3. 初始化过程中,初始值转换成变量的类型;在赋值语句中,右侧运算对象转换成左侧运算对象的类型。
4. 如果算术运算或关系运算的运算对象有多种类型,需要转换成同一种类型。
5. 如第6章将要介绍的,函数调用时也会发生类型转换。
算术转换
- 先进行整型提升
- 对于同时存在 有符号与无符号,若无符号类型不小于有符号(如int 与 unsigned int),则有符号转化为无符号(注意若此时int为负值会出现问题,但仍是一定的规则)
- 有符号类型大于无符号类型,则依赖于机器
int main()
{
int x = -1;
unsigned int y = 256;
unsigned int a = 0;
a = x + y ;
cout << a << endl;
a = (unsigned int)x + y ;
cout << a << endl;
//这里两次结果都是正确的,是由于先是转化(unsigned int)x 时出现异常,然后在相加时上溢了
}
其它隐式类型转换
类类型定义的转换
如
string s, t = "a value";
while(cin >> s)
条件(cin >>s)读入cin的内容并将cin作为求值结果。条件部分本来需要一个bool值,但实际检查的是istream类型的值。幸好IO库定义了从istream到bool的转换规则: 读入成功则为true,不成功则为false.
显示转换
一般形式为
cast-name <type> (expression);
type是转换的目标类型 而 expression为要转换的值,如果type是引用类型,则结果是左值
cast-name 是 static_cast, dynamic_cast, const_cast 和 reinterpret_cast 中的一种
static_cast
任何有明确定义的类型转换,只要不含有底层的const,都可以使用static_cast。
int j=3,i=2;
double slope = static_cast<double>(j)/i;
其次,当把大的算术类型给较小的时,可用来消除warning.
int i=3;
double x = 3.14;
i = static_cast<int>(x);
最后,可以用于找回存于void*中的值。
int main()
{
double d = 2.1;
void *p = &d;
double *dp = static_cast<double *>(p);
cout << p << endl;
cout << dp << endl;// p = dp
cout << *dp << endl;
}
const_cast
只能用于改变底层的const,去掉const性质,但无法改变表达式类型。
其次,若对象本身不是常量,则写值不会crash,但对常量进行写值会产生未定义的后果。
const char *cp;
char *q = static_cast<char*>(cp); //error: static_cast不能换掉const性质
static_cast<string>(cp);
//ok:字符串字面值转换成string类型
const_cast<string>(cp);
//error:const_cast只改变常量属性
reinterpret_cast
reterpret_cast为运算对象的位模式提供较为低层次上的解释。
就是截取二进制字符串后重新解释
这里结合位模式以char为例
int a = 21;
int *x = &a;
char ss = reinterpret_cast<char>(x);
当 x= 0x006ffa54时,由于本人Window10为大端机,那么实际在内存中储存为54 fa f6 00
然后 ss 会取到 0x54 转化为有符号的8bit的10进制数后对照ASCII表
为0x51 -> 2’b01010100 ->84 -> ‘T’
当 x= 0x012ffad4时,
0xd4 ->2’b 11010100 -> -44 -> 未定义