地址类型的强制转换(转载只是为了查阅⽅便,若有侵权,⽴
删)
当我们初始化⼀个指针或给⼀个指针赋值时,赋值号(=)的左边是⼀个指针,赋值号(=)的右边是⼀个指针表达式,在绝⼤多数情况下,指针的类型和指针表达式的类型是⼀样的,指针所指向的类型和指针表达式所指向的类型是⼀样的。
例⼀:
1、 float f=12.3;
2、 float*fptr=&f;
3、 int *p;
在上⾯的例⼦中,假如我们想让指针p指向实数f,应该怎么搞?是⽤下⾯的语句吗?
p=&f;
不对。因为指针p的类型是int*,它指向的类型是int,⽽表达式&f的结果是⼀个指针,指针的类型是float*,
它指向的类型是float。两者不⼀致,直接赋值的⽅法是不⾏的。⾄少在我的MSVC++6.0上,对指针的赋值语句要求赋值号两边的类型⼀致,所指向的类型也⼀致,其它的编译器上我没试过,⼤家可以试试。为了实现我们的⽬的,需要进⾏"强制类型转换":p=(int*)&f;
如果有⼀个指针p,我们需要把它的类型和所指向的类型改为TYEP*和TYPE,那么语法格式是:(TYPE*)p;这样强制类型转换的结果是⼀个新指针,该新指针的类型是TYPE*,它指向的类型是TYPE,它指向的地址就是原指针指向的地址。⽽原来的指针p的⼀切属性都没有被修改。
⼀个函数如果使⽤了指针作为形参,那么在函数调⽤语句的实参和形参的结合过程中,也会发⽣指针类型的转换。
例⼆:
voidfun(char*);
int a=125,b;
fun((char*)&a);
...
...
voidfun(char*s)
{
char c;
c=*(s+3);*(s+3)=*(s+0);*(s+0)=c;
c=*(s+2);*(s+2)=*(s+1);*(s+1)=c;
}
}
注意这是⼀个32位程序,故int类型占了四个字节,char类型占⼀个字节。函数fun的作⽤是把⼀个整数的四个字节的顺序来个颠倒(注意到了吗?),在函数调⽤语句中,实参&a的结果是⼀个指针,它的类型是int *,它指向的类型是int。形参这个指针的类型是char*,它指向的类型是char。这样,在实参和形参的结合过程中,我们必须进⾏⼀次从int*类型 到char*类型的转换,结合这个例⼦,我们可以这
样来想象编译器进⾏转换的过程:编译器先构造⼀个临时指针 char*temp,然后执⾏temp=(char*)&a,最后再把temp的值传递给s。所以最后的结果是:s的类型是char*,它指向的类型是char,它指向的地址就是a的⾸地址。
我们已经知道,指针的值就是指针指向的地址,在32位程序中,指针的值其实是⼀个32位整数。那可不可以把⼀个整数当作指针的值直接赋给指针呢?就象下⾯的语句:
unsigned inta;
TYPE*ptr;//TYPE是int,char或结构类型等等类型。
...
...
a=20345686;
ptr=20345686;//我们的⽬的是要使指针ptr指向地址20345686(⼗制
ptr=a;//我们的⽬的是要使指针ptr指向地址20345686(⼗进制)
编译⼀下吧。结果发现后⾯两条语句全是错的。那么我们的⽬的就不能达到了吗?不,还有办法:
unsigned inta;
TYPE*ptr;//TYPE是int,char或结构类型等等类型。
...
...
a=某个数,这个数必须代表⼀个合法的地址;
ptr=(TYPE*)a;//呵呵,这就可以了。
严格说来这⾥的(TYPE*)和指针类型转换中的(TYPE*)还不⼀样。这⾥的(TYPE*)的意思是把⽆符号整数a的值当作⼀个地址来看待。
上⾯强调了a的值必须代表⼀个合法的地址,否则的话,在你使⽤ptr的时候,就会出现⾮法操作错误。
想想能不能反过来,把指针指向的地址即指针的值当作⼀个整数取出来。完全可以。下⾯的例⼦演⽰
了把⼀个指针的值当作⼀个整数取出来,然后再把这个整数当作⼀个地址赋给⼀个指针:
例⼗六:
int a=123,b;
int*ptr=&a;
char *str;
b=(int)ptr;//把指针ptr的值当作⼀个整数取出来。
str=(char*)b;//把这个整数的值当作⼀个地址赋给指针str。
⼩结:可以把指针的值当作⼀个整数取出来,也可以把⼀个整数值当作地址赋给⼀个指针。
通过以上分析,我们可以思考下:什么是指针变量?
指针变量,本质上是⼀个变量,只是它是存放地址的变量,指针的类型代表的是它所指向的变量的类型。因此就有了指向整型、字符型、浮点型等其它类型的指针,但实际上所有类型的指针变量存放的都是int型(对于16位编译系统,⽐如 TC,int是2字节,对于32位编译系统,⽐如VC,GCC,int是4字节)
的地址。因此从本质上讲,不同类型的指针变量并没有区别(因为指针变量的类型 为int型,因此指针变量只能存放地址。注意和指针指向对象的类型区分开),指针变量所存储的地址为指针所指向的对象的⾸地址。
#include <stdio.h>
int main(void)
{
int * pint;
char * pchr;
float * pflt;
int a = 2;
char b = 3;
float c = 3.5;
pint = &a;
pchr = &b;
pflt = &c;
printf("pint = 0x%p/n",pint);
printf("pchr = 0x%p/n",pchr);
printf("pflt = 0x%p/n",pflt);
return 0 ;
}
输出结果:
pint = 0x0012FF3C
pchr = 0x0012FF33
pflt = 0x0012FF24
不同类型的指针变量之间的区别?
我们都知道不同类型的指针变量指向不同类型的对象,这些指针变量结合指针运算符(*)就等价于指向的对象的值,但我们⼜知道所有的指针变量的类型都是⼀样的(都是int型)。到底声明不同类型的指针变量的背后是什么?其实声明不同类型的指针变量既是规定了该变量结合指针运算符时读取内存中的字节数,同样在指针移动和指针的运算时(加、减)在内存中移动的最⼩字节数。
指针变量强制类型转换转换的背后
⾸先看个例⼦
#include <stdio.h>
int main(void)
{
int * pint;
char * pchr;
float * pflt;
int a = 2;
char b = 3;
float c = 3.5;
pint = &a;
pchr = &b;
pflt = &c;
printf("pint = 0x%p/n",pint);
printf("pchr = 0x%p/n",pchr);
printf("pflt = 0x%p/n",pflt);
/
/以上三句等同于下⾯三句吧?
printf("pint = 0x%p\n",&pint);
printf("pchr = 0x%p\n",&pchr);
printf("pflt = 0x%p\n",&pflt);
*(int *)0x0012FF3C =256; //a的⾸地址为0x0012FF3C printf("a = %d/n",a);
pchr = (char *)pint;
printf("*(int *)0x0012FF3C = %d/n",*pchr);
printf("*(int *)0x0012FF3D = %d/n",*(pchr + 1));
printf("*(int *)0x0012FF3E = %d/n",*(pchr + 2));
printf("*(int *)0x0012FF3F = %d/n",*(pchr + 3));
*(int *)0x0012FF3C = 125;
printf("a = %d/n",a);
pchr = (char *)0x0012FF3C;
printf("*(int *)0x0012FF3C = %d/n",*pchr);
printf("*(int *)0x0012FF3D = %d/n",*(pchr + 1));
printf("*(int *)0x0012FF3E = %d/n",*(pchr + 2));
printf("*(int *)0x0012FF3F = %d/n",*(pchr + 3));
return 0 ;
}
输出结果:
pint = 0x0012FF3C
pchr = 0x0012FF33指针变量本身有地址吗
pflt = 0x0012FF24
a =256
*(int *)0x0012FF3C = 0
*(int *)0x0012FF3D = 1
*(int *)0x0012FF3E = 0
*(int *)0x0012FF3F = 0
a = 125
*(int *)0x0012FF3C = 125
*(int *)0x0012FF3D = 0
*(int *)0x0012FF3E = 0
*(int *)0x0012FF3F = 0
由于 pchr ,pint是不同类型的指针变量,因此在pchr = (char *)pint;语句中需要进⾏强制类型转换转换。其实在此可以不理解成指针的强制类型转换(因为pint还是指向int型的指针,⾃⾝并没有任何改变),暂时可以将pint 理解成存储a变量的⾸地址的指针变量,这样就和pchr = (char *)0x0012FF3C语句等价,但由于pchr的声明为字符型的指针变量,因此等号的另⼀端应是⼀个字符型的地址,所以就
将0x0012FF3C声明(强制转化)为字符型的地址。但实际上地址本⾝就是地址,没有什么字符型、整型等区别的,只是为了⽅便说明,从理论上说的通,就认为是字符型的吧(个⼈是这样理解的)。同样*(int *)0x0012FF3C= 256 可以理解为在内存中⽤⼀个int型变量的⼤⼩的字节数来存储256这个值,⾸地址为0x0012FF3C。为了正确存储不同类型的数值,就需要将⾸地址声明不同类型的地址,来满⾜存储数据的要求。
综合代码演⽰:
1. #include "stdafx.h"
2. #include "iostream"
3. using namespace std;
4. class CA
5. {
6. public:
7. char c1;
8. char c2;
9. private:
0. };
1. class CB
2. {
3. public:
4. int i1;
5. int i2;
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论