C语言自动类型转换
![](https://i-blog.csdnimg.cn/blog_migrate/a5f34c5ca12e08fbb62a2f6b9fb5ac8b.png)
unsigned 即为 unsigned int ,此时可以省略int 只写unsigned
隐式的类型转换是安全的,而显示的类型转换是存在风险的。
C语言强制类型转换
C语言中 涉及
地址间强制类型转换
特别要注意 字节对齐 的问题;
unsigned int value = 1024; // 4 个 字节
cout << hex << &value << endl;
bool *p = (bool*)(&value);
cout << hex << p << endl;
p++;
cout << p << endl;
bool condition = *((bool *)(&value)); //(bool *)(&value);取的是第一位的地址
if (condition)
printf("condition=1");
else
printf("condition=0");
// 需要从大小端存储方式分析
struct point{
int a;
int *b;
}p;
p.a = 300;
p.b = (int*)500; // p.b为地址,地址,地址!!!!
// ptr指向地址为500的位置,其中的内容是未知的
// (前提是系统允许用户操作500这个地址)
printf("%d \n", 10 + p.a );// 值改变
printf("%d \n", 100 + p.a );
// p.b为地址,+表示偏移
printf("%d \n", p.b + 1); // 指针p.b偏移1 * 4,
printf("%d \n", p.b + 100); // 指针p.b偏移100 * 4
printf("%d \n", p.b + p.a); // 指针p.b偏移p.a * 4
C++ 强制类型转换
static_cast
static_cast<newType> (data)
double a = 19.95
int b = static_cast<int> (a)
适用于:
-
原有的自动类型转换。如:short -> int;
-
void指针和具体类型指针间的转换。如:void * -> int *、 char * -> void *
-
有转换构造函数或者类型转换函数的类与其它类型之间的转换。如 double 转 Complex(调用转换构造函数)、Complex 转 double(调用类型转换函数)。
不适用于:
-
两个具体类型指针之间的转换,例如int *转double *、Student *转int *等(不同类型数据存储格式、长度都不一样)
-
不能用来去掉表达式的 const 修饰和 volatile 修饰。换句话说,不能将 const/volatile 类型转换为非 const/volatile 类型。
const_cast
const_cast<newType> (data)
const int n = 100;
int *p = const_cast<int*>(&n);
*p = 12345;
const char *p = str1.c_str();
char* pp = const_cast<char*>(p);
它用来去掉表达式的 const 修饰属性或 volatile 修饰属性。换句话说,const_cast 就是用来将 const/volatile 类型转换为非 const/volatile 类型
dynamic_cast(
涉及到RTTI
)
使用形式如下:
dynamic_cast<type* >(e);
dynamic_cast<type& >(e);
dynamic_cast<type&& >(e);
type必须是一个类 类型,type 和 en 必须同时是指针类型或者引用类型或void *
对于指针,如果转换失败将返回 NULL;对于引用,如果转换失败将抛出std::bad_cast异常
dynamic_cast 用于在类的继承类之间进行类型转
换。
它依赖于RTTI(这就要求基类必须拥有虚函数,因为RTTI信息存储在虚函数表中),它允许向上转型也允许向下转型。
向上转型(派生类指针或引用转基类)是无条件的,不会进行任何检测,所以都能成功;(派转基)
向下转型(基类指针或引用转派生类)的前提必须是安全的,在程序运行期间要借助 RTTI 进行类型转换,这就要求基类必须包含虚函数,而static_cast在编译期间完成类型转换。(基转派)
e能成功转换为type*类型的情况有三种:
1)e的类型就是type的类型时,一定会转换成功(不要求有虚函数的限定)。(本身转换)
2)e的类型是目标type的公有派生类:派生类向基类转换一定会成功(不要求有虚函数的限定)。(派转基)
3)e的类型是目标type的基类,(基类必须要有虚函数)(基转派)
当e是指针指向派生类对象,或者基类引用引用派生类对象时,类型转换才会成功,
当e指向基类对象,试图转换为派生类对象时,转换失败。
![](https://i-blog.csdnimg.cn/blog_migrate/63edebb8a6633e6a15fdd604fd708c39.png)
注:上指父类(基类),下指子类(派生类)
reinterpret_cast
reinterpret_cast<newType> (data)
char str[]="abcdefgh";
float *p1 = reinterpret_cast<float*>(str); //用一个 float 指针来操作一个 char 数组是一件多么荒诞和危险的事情
cout<<*p1<<endl;
是“重新解释”的意思,顾名思义,reinterpret_cast 这种转换仅仅是对二进制位的重新解释,不会借助已有的转换规则对数据进行调整,
非常简单粗暴,所以十分危险,不到万不得已时应避免使用。
可以用于两个具体类型指针之间的转换、int 和指针之间的转换(有些编译器只允许 int 转指针,不允许反过来)。