指针强制转换
- 格式:doc
- 大小:37.00 KB
- 文档页数:5
dynamic_cast运算符dynamic_cast可以针对两种数据类型做强制转换:指针类型和引用类型。
这两种类型的情况是不一样的。
下面讨论如下:1、对指针的强制转换dynamic_cast<T*>(p);如果p的类型为T*,或者为D*,且T是D的一个可以访问的基类,结果跟我们直接将p 赋给一个T*是一样的。
(这是向上类型转换的情况)。
dynaimic_cast的专长是用于那些编译器无法确定转换正确性的情况。
在这种情况下dynamic_cast将查看被p指向的对象(如果有的话),如果这个对象属于类T,或者有唯一的基类T,那么dynamic_cast就返回指向该对象的类型为T*的指针。
否则就返回0。
如果p 的值为0,则dynamic_cast<T*>(p)也返回0。
如果要做向下的类型转换,或者兄弟类之间做交叉转换,则要求p是一个到多态类型的指针或引用。
但是转换的目标类型不一定是支持多态的。
因为如果p的类型不是T的,那么返回值为0,这样的话,我们对dynamic_cast<T*>(p)的返回值必须做显示的检查。
对于指针p,dynamic_cast<T*>(p)可以看成一个疑问:p所指向的对象的类型是T吗?2、对引用的强制转换因为我们能合法的假定一个引用总是引用着某个对象,因此对引用r做dynamic_cast<T&>(r)不是提问,而是断言:“由r引用的对象的类型是T”。
对于引用的dynamic_cast的结果,隐式的由dynamic_cast去做检查,如果对引用的dynamic_cast不具有所需要的类型,就会跑出一个bad_cast异常。
在对动态指针强制转换和动态引用强制转换结果方面的差异,所反应的正是指针和引用之间的根本性差异。
////////////////////////////////////////////////////////////////////C++的数据类型转换dynamic_cast2007年04月26日星期四下午 06:13(一)在使用C++编程时,经常要用到不同数据类型之间的类型转换,可能大家对C 语言的类型强制转换比较熟悉,就是在表达时前面加一个“(强制转换类型)”。
在C++中存在两种转换:隐式转换和显式转换(强制转换)。
一、隐式类型转换C++定义了一组内置类型对象之间的标准转换,在必要时它们被编译器隐式地应用到对象上。
隐式类型转换发生在下列这些典型的情况下;1、在混合类型的算术表达式中。
在这种情况下,最宽的数据类型成为目标转换类型。
这也被称为算术转换arithmetic conversion 例如:int ival = 3;double dval = 3.14159;// ival 被提升为double 类型: 3.0 (是一种保值转换)ival + dval;2、用一种类型的表达式赋值给另一种类型的对象。
在这种情况下,目标转换类型是被赋值对象的类型。
例如,在下面第一个赋值中文字常量0 的类型是int 它被转换成int*型的指针表示空地址在第二个赋值中double 型的值被截取成int 型的值。
// 0 被转换成int*类型的空指针值int *pi = 0;// dval 被截取为int值3 (这不是保值转换),一般情况下编译器会给出warning.ival = dval;3、把一个表达式传递给一个函数调用,表达式的类型与形式参数的类型不相同。
在这种情况下,目标转换类型是形式参数的类型。
例如:extern double sqrt( double );// 2 被提升为double 类型: 2.0cout4、从一个函数返回一个表达式,表达式的类型与返回类型不相同。
在这种情况下,目标转换类型是函数的返回类型。
例如:double difference( int ival1, int ival2 ){// 返回值被提升为double 类型return ival1 - ival2;}二、显示转换(强制转换)(一)、旧式强制类型转换:由static_cast,cons_cast 或reinterpret_cast 强制转换符号语法,有时被称为新式强制转换符号,它是由标准C++引入的。
c 强制类型转换 const
在C语言中,强制类型转换是一种将一个数据类型转换为另一
个数据类型的操作。
在进行强制类型转换时,我们可以改变一个变
量的数据类型,以便在表达式中使用该变量。
在进行强制类型转换时,我们可以使用强制类型转换运算符来实现,它的一般形式是(type_name) expression,其中 type_name 是我们希望将expression 转换为的类型。
在进行强制类型转换时,我们需要注意
以下几点:
1. 强制类型转换可能会导致数据丢失,当我们将一个较大的数
据类型转换为一个较小的数据类型时,可能会导致数据丢失。
例如,将一个浮点数转换为整数时,小数部分将被截断。
2. 强制类型转换可能会改变数据的含义,有时候,我们可能会
将一个数据类型转换为另一个数据类型,这可能会改变数据的含义。
例如,将一个指针转换为整数,可能会丢失指针所指向的对象的信息。
当我们进行 const 强制类型转换时,我们可以使用
const_cast 运算符来实现。
const_cast 是 C++ 中的一个运算符,
它可以用来移除对象的 const 属性,从而允许修改被 const 修饰的对象。
但是需要注意的是,对于 const 对象,我们应该谨慎地使用 const_cast 运算符,因为这可能会导致未定义的行为。
总的来说,强制类型转换是一种有用的工具,但是在使用时需要谨慎,以避免可能导致的数据丢失和未定义的行为。
函数指针强转
函数指针强转,是指将一个函数指针数据类型转换为另一个函数指针
数据类型。
在C语言中,函数指针是指向函数的指针变量,可以将函
数指针作为参数传递给其他函数,也可以将函数指针作为返回值返回。
一般情况下,函数指针强转是指将一个函数指针数据类型转换为另一
个函数指针数据类型,这可以用于将指向不同函数的指针强制转换为
相同的类型,这样可以在编译时避免出现类型不匹配的问题。
在C语言中,函数指针强转的语法格式如下:
(return_type (*new_type)(arguments)) pointer_expression;
其中,return_type表示函数的返回值类型,new_type表示需要将函数指针转换为的新类型,arguments表示函数的参数类型,
pointer_expression表示需要进行强制类型转换的函数指针。
需要注意的是,将函数指针强转时,需要确保转换后的函数指针可以
正确地执行指向的函数。
如果强制类型转换不正确,可能导致程序崩
溃或者出现其他错误。
除了将函数指针强转为相同的函数指针类型之外,还可以将其强制转换为void类型的函数指针,这可以使用在需要将函数指针参数传递给不同的函数时,将其作为通用的参数类型传递。
总之,函数指针强转可以用于将不同类型的函数指针转换为相同的类型,以便在编译时避免类型不匹配的问题。
但需要注意,必须确保转换后的函数指针可以正确地执行指向的函数。
在C语言中,函数指针是一种特殊类型的指针,可以用来存储和传递函数的地址。
函数指针可以在编译时或者运行时被调用,并通过参数和返回值来传递数据。
强制类型转换是将一个类型的值转换为另一个类型。
在C语言中,强制类型转换可以使用强制类型转换运算符(`(type)`)来完成。
参数个数不对是指在调用函数时,传递给函数的参数数量与函数定义中的参数数量不匹配。
这可能会导致编译错误或者运行时错误。
如果将函数指针强制转换并传递参数个数不对,会导致以下几种情况:
1. 编译错误:如果参数个数与函数定义中的参数数量不匹配,编译器会报错,导致编译失败。
2. 运行时错误:如果参数个数与函数定义中的参数数量不匹配,但编译器没有报错,那么在运行时可能会出现错误。
这可能会导致程序崩溃或者出现未定义的行为。
3. 未定义行为:如果函数指针强制转换后,调用的函数和原始函数具有不同的参数个数和类型,那么可能会出现未定义的行为。
这可能会导致程序出现不可预测的结果或错误。
因此,在使用函数指针时,应该确保传递给函数的参数个数和类型与函数定义中的参数个数和类型一致,以避免出现编译错误、运行时错误或未定义行为。
c语言结构体指针强制类型转换
在C语言中,结构体是一种自定义数据类型,它由多个变量(成员)组成。
通常情况下,我们需要使用结构体指针来操作结构体变量。
但是有时候我们需要将一个结构体指针强制类型转换为另一个结构
体指针类型,以便于对其进行不同的操作。
C语言中的强制类型转换使用了一个特殊的符号“()”,格式如下:
(目标类型)表达式
其中,目标类型是要转换成的类型,表达式则是要进行转换的值。
在进行结构体指针的强制类型转换时,我们需要注意以下几点:
1. 转换后的结构体指针类型必须与原类型有相同的成员变量或者成员变量的类型,否则会导致程序运行错误。
2. 强制类型转换只改变指针类型,不改变指针所指向的内存区域,因此需要保证转换后的指针指向的内存区域是合法的。
3. 在进行结构体指针的强制类型转换时,我们应该尽量避免对指针所指向的内存区域造成不必要的影响,以免引起程序运行错误或安全问题。
总之,结构体指针的强制类型转换是C语言中非常重要的一个操作,需要在程序中谨慎使用,以确保程序的正确性和安全性。
- 1 -。
c语言强制类型转换的方法和原则
C语言中的强制类型转换可以通过使用类型转换运算符来实现,即将要转换的目标类型放在圆括号中,紧跟着要转换的表达式。
强制类型转换的原则如下:
1. 在进行类型转换之前,需要确保转换是安全和合理的。
比如,将一个较大的整数类型转换为较小的整数类型可能导致数据溢出或精度丢失。
2. 强制类型转换可以用于基本数据类型(如整数、浮点数)之间的转换,也可以用于指针类型之间的转换。
3. 当进行指针类型之间的转换时,需要格外注意,确保指针类型的大小相同或兼容。
否则,可能会导致访问越界或产生未定义的行为。
4. 在进行强制类型转换时,应当尽量避免对指针类型进行转换,特别是将一个指向非相关类型的指针转换为另一个指针类型,因为这可能会破坏内存的完整性及程序的健壮性。
5. 强制类型转换应该谨慎使用,只在必要时才使用。
过多地依赖强制类型转换可能导致代码的可读性和可维护性下降,同时也增加了代码出错的风险。
总之,强制类型转换是一种强制改变数据类型的操作,但需要谨慎使用,确保转换的安全性和合理性。
在进行强制类型转换时,应遵循上述原则,并尽量保持代码的简洁和易读。
结构体强制转换指针
结构体强制转换指针是指在C或C++中,将一个结构体类型的
指针转换为另一个结构体类型的指针。
这种转换通常用于需要在不
同类型的结构体之间共享数据或者进行类型转换的情况下。
在C语言中,可以使用强制类型转换来实现结构体指针的转换。
例如,如果有一个指向结构体A的指针,想要将其转换为指向结构
体B的指针,可以使用如下的语法:
c.
struct A {。
int x;
};
struct B {。
int y;
};
struct A ptrA;
struct B ptrB;
ptrB = (struct B )ptrA;
在上面的例子中,ptrA 是一个指向结构体 A 的指针,ptrB 是一个指向结构体 B 的指针。
通过使用强制类型转换,我们将 ptrA 转换为指向结构体 B 的指针,并将其赋值给 ptrB。
需要注意的是,结构体的强制类型转换可能会导致数据的不一致性或者错误,因此在进行结构体指针的强制转换时,需要确保转换的目标结构体类型和原始结构体类型之间有一定的关联或者相似性,以避免出现错误的结果。
另外,在C++中,可以使用 static_cast 或者
reinterpret_cast 来进行结构体指针的强制转换,这些转换操作符提供了更加灵活和安全的类型转换方式,可以在一定程度上避免一些潜在的问题。
总之,结构体指针的强制转换是一种在C或C++中常见的操作,但需要谨慎使用,以确保转换的安全性和正确性。
c语⾔的指针强制类型转换强制类型转换分为两种情况:情况1、⽤malloc分配内存时如:Test2 *test2 = (Test2 *)malloc(sizeof(Test2));2、将⼀个已知指向某类型的指针转换成其他类型的指针如:typedef struct Test0{int a ;//int c;} Test0;typedef struct Test1{Test0 *test0;} Test1;typedef struct Test2{Test1 test1;//执⾏通过int b;int a;//Test1 test1;//执⾏⽆法通过} Test2;void main(){Test2 *test2 = (Test2 *)malloc(sizeof(Test2));Test0 test0;test0.a = 111; //下⾯的这句为什么会执⾏成功呢?((Test1*)test2)->test0 = &test0;cout << test2->test1.test0->a << endl;}以上就是两种类型的指针类型强制转换红⾊字的疑问,将test2指针变量的由Test2强制转换为Test1,为什么可以成功呢?事实上这种想法本⾝就是错的"将test2指针变量的由Test2强制转换为Test1","指针类型的强制转换"事实上本⾝就是⼀种错误的想法.在指针是没有类型强制转换的.这⾥事实上就是没弄清什么是指针指针要弄清四部分:指针本⾝是什么类型、指针所指向的类型是什么、指针本⾝的值是多少、指针所指向的地址存的值是多少?情况1:Test2 *test2 = (Test2 *)malloc(sizeof(Test2));这⾥要这么理解 test2是⼀个Test2*类型的指针变量,,⽽malloc(sizeof(Test2))返回的是⼀个void*类型的内存区的⾸地址,那么这个内存区要由Test2类型的指针来指向,那他当然要把这个⾸地址开始的某区域转换成Test2类型,以让test2进⾏操作情况2:((Test1*)test2)->test0 = &test0;这个代码是如何能执⾏呢?原因是test2指向的是⼀种Test2类型的内存区的⾸地址,⽽Test2的第⼀个成员test1是Test1类型的,所以事实上该⾸地址事实上也是test1的⾸地址所以test2可以把test2的所指向的⾸地址由test1类型的指针来指向。
c语言指针类型强制转换
在 C 语言中,指针类型的强制转换可以通过以下两种方式进行:
1. 显式类型转换
显式类型转换是指在指针表达式中使用类型转换运算符来指定指针所指向数据类型的转换。
例如,如果要将一个指向int 类型的指针转换成指向float 类型的指针,可以使用以下代码:
```c
int *p; // 定义一个指向int 类型的指针
float *q = (float *)p; // 将p 转换成指向float 类型的指针
```
在上面的代码中,使用强制类型转换运算符`(float *)` 将指针`p` 转换成指向float 类型的指针`q`。
2. 隐式类型转换
隐式类型转换是指编译器自动进行指针类型的转换。
在某些情况下,隐式类型转换可能会导致数据丢失或精度损失。
例如,如果将一个指
针强制转换为一个整数,那么指针所指向的地址可能会被错误地解释为一个数字。
为了避免隐式类型转换带来的问题,应该尽量避免将指针强制转换为其他类型,除非确实需要这样做。
如果必须进行类型转换,应该使用显式类型转换。
需要注意的是,如果指针所指向的数据类型和目标类型不匹配,编译器将会产生编译错误。
因此,在进行指针类型转换时,必须确保指针所指向的数据类型和目标类型是匹配的。
c 一级指针强制转换二级指针的方法首先,我们需要了解一级指针和二级指针的概念。
一级指针是一个指向内存地址的变量,而二级指针则是一个指向一级指针的指针。
在C语言中,一级指针强制转换为二级指针的方法可以通过使用取址和指针类型转换来实现。
下面我们将一步步回答这个问题。
步骤1:了解指针类型首先,我们需要明确一级指针和二级指针的类型。
在C语言中,指针类型的定义是通过在指针变量前添加一个"*"符号来实现的。
例如,int *p1; 表示p1是一个一级指向int类型变量的指针,而int p2; 表示p2是一个二级指向int类型变量的指针。
步骤2:为一级指针和二级指针变量分配内存在进行强制转换之前,我们需要首先创建一级指针和二级指针变量,并为它们分配内存空间。
这可以通过使用malloc()或者calloc()函数来完成。
下面是一个示例代码:cint main() {int *p1;int p2;为一级指针变量分配内存p1 = (int *)malloc(sizeof(int));为二级指针变量分配内存p2 = (int )malloc(sizeof(int *));... 程序的其他部分return 0;}步骤3:进行指针类型的强制转换一旦我们为一级指针和二级指针变量分配了内存空间,我们就可以进行一级指针到二级指针的强制转换。
这可以通过对一级指针进行取址操作(&),然后进行指针类型的转换实现。
下面是一个示例代码:cint main() {int *p1;int p2;为一级指针变量分配内存p1 = (int *)malloc(sizeof(int));为二级指针变量分配内存p2 = (int )malloc(sizeof(int *));将一级指针强制转换为二级指针*p2 = (int *)p1;... 程序的其他部分return 0;}在这个示例代码中,我们首先将一级指针变量p1强制转换为int类型的指针。
C++中的数据类型强制转换⽅法1. c强制转换与c++强制转换c语⾔强制类型转换主要⽤于基础的数据类型间的转换,语法为:(type-id)expression//转换格式1type-id(expression)//转换格式2c++除了能使⽤c语⾔的强制类型转换外,还新增了四种强制类型转换:static_cast、dynamic_cast、const_cast、reinterpret_cast,主要运⽤于继承关系类间的强制转化,语法为:static_cast<new_type> (expression)dynamic_cast<new_type> (expression)const_cast<new_type> (expression)reinterpret_cast<new_type> (expression)备注:new_type为⽬标数据类型,expression为原始数据类型变量或者表达式。
《Effective C++》中将c语⾔强制类型转换称为旧式转型,c++强制类型转换称为新式转型。
2. static_cast、dynamic_cast、const_cast、reinterpret_caststatic_caststatic_cast相当于传统的C语⾔⾥的强制转换,该运算符把expression转换为new_type类型,⽤来强迫隐式转换,例如non-const对象转为const对象,编译时检查,⽤于⾮多态的转换,可以转换指针及其他,但没有运⾏时类型检查来保证转换的安全性。
它主要有如下⼏种⽤法:①⽤于类层次结构中基类(⽗类)和派⽣类(⼦类)之间指针或引⽤的转换。
进⾏上⾏转换(把派⽣类的指针或引⽤转换成基类表⽰)是安全的;进⾏下⾏转换(把基类指针或引⽤转换成派⽣类表⽰)时,由于没有动态类型检查,所以是不安全的。
②⽤于基本数据类型之间的转换,如把int转换成char,把int转换成enum。
c语言强制转换与乘法运算优先级C语言是一门非常重要的编程语言。
在C语言中,强制转换和运算优先级是非常重要的概念。
以下是对于这两个概念的详细解释:强制转换:强制转换是C语言中的一种类型转换方法。
它可以将一种数据类型转换为另一种数据类型。
在强制转换中,我们可以使用强制转换操作符“()”来进行类型转换。
强制转换的语法如下:(type_name) expression其中,type_name是要转换的数据类型,expression是要被转换的表达式。
在强制转换中,我们需要注意以下几点:1. 强制转换可能会造成精度损失。
例如,将一个double类型转换成int 类型时,小数部分将被截断。
2. 强制转换可能会产生未定义的行为。
例如,将一个非指针类型的整数转换成一个指针类型时,可能会导致访问非法内存。
3. 在进行强制转换时,我们应该尽量避免使用旧的C风格转换。
新的C++风格转换可以提供更好的安全性和可读性。
乘法运算优先级:在C语言中,乘法运算的优先级高于加法运算。
因此,在复合表达式中,乘法运算会先于加法运算执行。
如果我们想改变乘法和加法运算的执行顺序,我们可以使用圆括号来显式地指定优先级。
例如,以下代码中,变量a、b和c的值将被先相加,然后再与变量d相乘:int a = 1, b = 2, c = 3, d = 4;int result = (a + b + c) * d;记住,加上圆括号可以提高代码可读性,也可以减轻因优先级问题而带来的错误。
总结:强制转换和运算优先级是C语言中的重要概念。
强制转换可以帮助我们将一个数据类型转换成另一个数据类型,但需要注意潜在的精度损失和未定义行为。
而乘法运算优先级可以帮助我们正确地执行复合表达式中的计算,但需要注意使用圆括号来显式地指定优先级。
熟练掌握这些概念可以帮助我们更好地理解C语言中的代码。
c cast函数C语言是一种十分常用的编程语言,其具有强大的表达能力和代码灵活性。
在C语言中,有一个十分常用的函数——c cast函数。
那么,什么是c cast函数呢?它又有什么特点和应用呢?本文将为各位简单介绍。
C cast函数是C语言中的类型转换函数,其主要功能是将一种数据类型的值转换为另一种数据类型的值。
C cast函数主要有四种类型:强制类型转换、指针类型转换、算术类型转换和脱引用类型转换。
首先,让我们来看一下强制类型转换。
在C语言中,所谓强制类型转换就是将一个变量或者表达式的值强制转换为另一种数据类型。
强制类型转换的语法格式为:(转换类型)要转换的数据。
例如:(float)1/2将1/2的结果强制转换为浮点型。
其次,让我们来看一下指针类型转换。
在C语言中,指针类型转换就是将一个指针变量的数据类型转换为另一种类型。
指针类型转换的语法格式为:(转换类型 *)要转换的指针。
例如,将一个int类型的指针转换为float类型的指针,就可以使用(float *)p。
接下来,让我们来看一下算术类型转换。
在C语言中,算术类型转换就是将程序中出现的一种算术类型自动转换为另一种类型。
例如,如果程序中出现了一个short int类型的变量和一个long int类型的变量,则在运算时C语言将把short int类型的变量转换成long int类型的变量。
最后,让我们来看一下脱引用类型转换。
在C语言中,脱引用类型转换可以将一个指针变量脱引用成指向的数据类型。
脱引用类型转换的语法格式为:*(转换类型 *)要转换的指针。
例如,将一个char类型指针p脱引用成int类型就可以使用*(int *)p。
总的来说,C cast函数是C语言中非常实用的函数,它可以灵活地实现各种类型转换的需求。
当然,在使用C cast函数时,也需要注意关注类型转换的安全性和正确性,避免程序运行出现错误。
希望本文能为大家提供一些帮助。
c++中的强制转换⼀、C语⾔的强制转换1.1 隐性转换 不同数据类型之间赋值和运算,函数调⽤传递参数等等,由编译器完成int nTmp = 10;short sTmp = nTmp; //这个时候就需要注意转换时数据是否溢出(⼤字节转⼩字节)1.2 显性转换 在变量的前⾯加上(Type)进⾏显性转换,如:class Test;Test *test;T* obj = (T*)test;//将对象强制转换成T⼆、C++语⾔的转换 C++语⾔的强制有由四个标准的转换符组成;static_cast、const_cast、dynamic_cast、reinterpret_cast,除前⾯四个转换符,C++也继承了C语⾔的强制转换,但这种转换并不是安全和严格的。
2.1 static_cast ⽤法:static_cast < typeid > ( exdivssion )该运算符把exdivssion转换为typeid类型,但没有运⾏时类型检查来保证转换的安全性。
它主要有如下⼏种⽤法:①⽤于类层次结构中基类和⼦类之间指针或引⽤的转换。
进⾏上⾏转换(把⼦类的指针或引⽤转换成基类表⽰)是安全的; 进⾏下⾏转换(把基类指针或引⽤转换成⼦类表⽰)时,由于没有动态类型检查,所以是不安全的。
②⽤于基本数据类型之间的转换,如把int转换成char,把int转换成enum。
这种转换的安全性也要开发⼈员来保证。
③把空指针转换成⽬标类型的空指针。
④把任何类型的表达式转换成void类型。
注意:static_cast不能转换掉exdivssion的const、volitale、或者__unaligned属性。
2.2dynamic_cast ⽤法:dynamic_cast < typeid > ( exdivssion )该运算符把exdivssion转换成typeid类型的对象。
Type-id必须是类的指针、类的引⽤或者void *;①如果type-id是类指针类型,那么exdivssion也必须是⼀个指针,如果type-id是⼀个引⽤,那么exdivssion也必须是⼀个引⽤。
1、指针类型转换请使用static_cast、dynamic_cast等操作
2、指针变量(不管那种指针),大小都是四个字节,内容就是指向的对象的首地址。
不同类型指针不同点就是对首地址之后的那块内存会做不同解释。
建议你看看《Inside C++ Object Model》里面关于指针的内容,里面有清晰的说明
int * pi = new int;
pi 指向了一块内存的首地址,这块内存应该有sizeof(int)个字节,
由于pi是int *类型,所以通过pi进行的操作,编译器都认为pi的内容是一个有sizeof(int)个字节的int 型变量的首地址,所以*pi = 4,遇到这样的操作,编译器产生的代码就是把4这个数付到pi所指的四个字节里。
char * pc = (char *)pc; //建议这样写char * pc = static_cast <char *> (pc);
*pc = '4 ';
由于pc是char *类型,所以通过pc进行的操作,编译器都认为pc的内容是一个有sizeof(char)个字节的char型变量的首地址,所以*pc = '4 ',遇到这样的操作,编译器产生的代码就是把4这个字符付到pc所指的第一个字节里。
虽然,pc实际指向的是int型的变量,有4个字节。
改变指针的类型,解引用操作的时候会影响到所指向的地址内容(类型所占的字节数可能不同,还有高位是符号位或是数据位)解析,不会发生数据丢失
未必!设想下面三个类:
class A
{
public:
int m_nA;
A():m_nA(1){}
public:
A* GetA(){ return this; }
};
class B
{
public:
int m_nB;
B():m_nB(2){}
};
class C : public A, public B
{
public:
int m_nC;
C():m_nC(3){}
};
int main()
{
C *c = new C;
此处调试察看c指向的内存空间,假设以c的指向为基点,其后的地址以偏移记
那么整个c所指向的对象在内存中的排列如下:
(0)四个字节的m_nA (4)四个字节的m_nB (8)四个字节的m_nC (12)......
这里只关心最前面的12个字节,再看:
A *a = c-> GetA();
此处察看a,和c一样,它也指向上面的(0)处。
这没有问题,通过它来访问
m_nA会得到1,完全正确。
再看:
B *b = (B*)a;
此处得到的b和a的指向完全一样,通过它来访问m_nB得到的值是不正确的。
不
过,如果通过它来访问B的非虚的成员函数,可以得到正确的结果。
这里的强制转换仅仅是改变了指针的类型。
看下面最关键的:
b = (C*)a;
b居然指向了(4)处,这句代码居然得到了正确的地址!也就是说,这里的强制
转换不仅改变了指针的类型,同时也改变了指针的值。
为什么?
return 1;
}
把指向派生类的指针,转换为不是第一个基类的指针时,必须要对其地址做出改变
这样才可以使派生类指向该基类,这点inside the c++ object model书上讲了的
关于这里:
B *b = (B*)a;
此处得到的b和a的指向完全一样,通过它来访问m_nB得到的值是不正确的。
不过,如果通过它来访问B的非虚的成员函数,可以得到正确的结果。
这里的强制转换仅仅是改变了指针的类型
由于a是个指向类型A的指针,这种转换就和派生类毫无关系,仅是将一个类的指针
转换为指向另一个类(相当于这两个类没有任何联系,实际上A,B之间是毫无联系的)
并不像这样
b = (C*)a;,a转换为C的指针后,b和c有了基类和派生类的关系
问题就是关于*b的,b是一个指向char型的指针,将&a解释成(char*)的类型,从而*b也就是a的最高位的那个字节,所以我感觉*b结果应该是0x000000ff,那里错了?
char * b = (char *)&a;
是将a的地址转换成char *类型,实际上就是b存放a这个变量的地址。
也就是说b指向了a所以对b进行解引用得到的就是a了
因为你用的是x86 CPU,将整形的高字节放在地地址处,也就字节顺序从高到低,地址从低到高顺序0xff fffff7
1)little-endian的话,*b指向的是最低的那个字节也就是f7,这个上面已经说过了;
2)我想补充的是,即使指向的是高位字节,你的输出也不是0x000000ff,而是全f,符号位扩展的原因char相当有符号的整数,所以打印fffffff7.
如果是:
unsigned char * b = (unsigned char *)&a;
那么也打印000000f7
其实b指向的就是最后一个字节f7,而char是有符号的,高位用ff补齐,而unsigned是无符号的,就直接打印一个字节的内容,高字节就用0补齐
#include <stdio.h>
int main(void)
{
unsigned int a = 0xfffffff7;
unsigned char i = (unsigned char)a;
char * b = (char *)&a;
unsigned char * c = (char *)&a;
int d = *b;
int e = *c;
printf("%08x\n%08x %08x %d %d\n", i, *b, *c, d,e);
return 0;
}
打印结果:
000000f7
fffffff7 000000f7 -9 247
我们用2进制来写这些数字,并且参考6楼,增加一个unsigned char的指针或者数字。
为了书写方便,我这里都直接取数了,不进行指针操作。
unsigned int a = 1111 1111 1111 1111 1111 1111 1111 0111
因为a是无符号型,所以最高位的1是表示2的63次方。
unsigned char i = 1111 0111
char b = 1111 0111
unsigned char c = 1111 0111
注意b的最高位的1,并不是表示2的7次方,而是表示b是负数。
所以查看他们的值,会发现,b是-9.利用补码加1,可以算出确实是-9,c和i都是247,也可以算出来。
所以int到char 的强制转换,不管是不是无符号型,肯定是截取了低16位。
什么呢?因为c/c++标准规定char类型可以是signed char,也可以是unsigned char,这就是实现相关。
编译器可以自行选择其中一种,一般情况下编译器会
提供选项让用户选择。
你所得到的结果,是因为你当前编译环境设定char是signed char而得到的。
由于*b是signed char,在作为参数传入printf之前,*b被自动提升为int,这是一个到signed int的转换,
标准规定在这种情况下,如果*b的值能被signed
int 表示,那么值不变,*b的值为f7,在signed char里表示-9,那么转换为signed int后它也应该保持-9这个值,-9在四字节signed int里面就是
fffffff7,因此才有*b = fffffff7的结果,事实上,这里从f7到fffffff7的转换就叫做符号扩展。
如果编译器设定char是unsigned char,情况就与i相同了,无符号f7值是247,转换为signed int后应该依然还是247,因此就是000000f7了。
实际上这些类型最终都是有最基本的几个类型定义的,
所以有一些类型之间只是名称不同,内涵是一致的,
指针类型是C的最强大的内容,只要转换成相应的类型指针,
就能按照目标类型来读写指针指向的空间,而不用理会它原来是什么类型。