C++中打印数据类型typeid(var).name()
C中的强制类型转换并不改变数据在内存中实际存储的值,只是修改了对这段内存解释的方式。
因此C语言里面的强制类型转换也就存在了一些几个缺点:
int test_c_cast() {
short s1 = -1;
unsigned short s2 = (unsigned short)s1;
std::cout << "s1: " << s1 << "; s2: " << s2 << "\n";
unsigned short s3 = 32768;
short s4 = (short)s3;
std::cout << "s3: " << s3 << "; s4: " << s4 << "\n";
char c1 = -128;
unsigned short s5 = (unsigned short)c1;
std::cout << "c1: " << c1 << "; s5: " << s5 << "\n";
int i1 = -800008;
unsigned short s6 = (unsigned short)i1;
std::cout << "i1: " << i1 << "; s6: " << s6 << "\n";
unsigned int ui2 = 4294967295;
float f1 = (float)ui2;
std::cout << "ui2: " << ui2 << "; f1: " << f1 << "\n";
float f2 = -100.11;
int i2 = (int)f2;
std::cout << "i2: " << i2 << "; f2: " << f2 << "\n";
return 0;
}
测试结果:
s1: -1; s2: 65535
s3: 32768; s4: -32768
c1: �; s5: 65408
i1: -800008; s6: 51960
ui2: 4294967295; f1: 4.29497e+09
i2: -100; f2: -100.11
由于C中强制转换的缺点,C++中引入了一下几种类型转换。
const_cast常用于修改遍历的const属性,把变量的const属性干掉。返回的是一个变量的指针或者引用。因此模板的值也需要是引用或者指针。
样例代码:
int test_cpp_const_cast() {
const int ci1 = 33;
//ci1 = 11; // error: assignment of read-only variable
int i2 = const_cast<int&>(ci1);
i2 = 11;
std::cout << "ci1: " << ci1 << ", ci1 addr: " << &ci1 <<"; i2: " << i2 << ", i2 addr: " << &i2 <<"\n";
const int *cpi = new int(44);
int *i3 = const_cast<int *>(cpi);
*i3 = 22;
std::cout << "*cpi: " << *cpi << "; *i3: " << *i3 << "\n";
delete cpi;
const int ci2 = 55; //不加volatile的话,直接读取的是寄存器的值,下面更新后值不会更新
int *i4 = const_cast<int *>(&ci2);
*i4 = 77;
std::cout << "ci2: " << ci2 << ", ci2 addr: " << &ci2 << "; *i4: " << *i4 << ", i4 addr: " << i4 << "\n";
return 0;
}
static_cast会在编译过程中进行安全性检查,相对于dynamic_cast是静态转换。但是不能保证是安全转换,需要程序员自己保证。编译器隐式执行的任何类型转换都可用static_cast。
通常使用场景:
代码样例:
int test_cpp_static_cast() {
int i1 = 50000;
short s1 = static_cast<short>(i1); //不安全转换
std::cout << "i1: " << i1 << "; s1: " << s1 << "\n";
void * p = malloc(16);
memset(p, 1, 16);
unsigned short *s2 = static_cast<unsigned short *>(p);
std::cout << "s2: " << *s2 << "\n";
void * p = malloc(16);
memset(p, 1, 16);
int *i2 = static_cast<int *>(p); //不安全转换
std::cout << "i2: " << *i2 << "\n";
return 0;
}
dynamic_cast一般用于基类和派生类之间的转换。在运行时会进行检查,属于动态转换。
对于向下转换与static_cast的功能相同。对于向上转换dynamic_cast会进行类型检查,更安全。
几点注意事项:
类似于C的类型转换,并不修改内存中的值,只是指定了内存中值的解释方式。
用于指针或者引用之间的相互转换。或者将int型转换为指针,将指针转换为int型。
测试代码:
int test_cpp_reinterpret_cast() {
int * pi = new int(55);
unsigned long long addr = reinterpret_cast<int>(pi);
std::cout << "pi: " << pi << "; addr: " << addr << "\n";
float *pf = reinterpret_cast<float *>(pi); //不安全转换
std::cout << "pi: " << pi << "; pf: " << pf << "\n";
std::cout << "*pi: " << *pi << "; *pf: " << *pf << "\n";
return 0;
}