C/C++指针类型强制转换解析

指针类型的强制转换

Three q

Q1

指针的强制类型转换,必须显式,指向空间的强制类型转换,本质上就是普通变量的强制类型转换。

指针本身强制类型转换,改变的是对其指向空间的引用方式(空间大小和存储结构)

int a = 10;
int *pa = &a;
float *pb = NULL;
pb = (float *)pa; // 或者 pb = (float *)&a;

​ 当 指针pa存放的地址强制转换成float之后, 赋值给pb。pb里面的地址值与pa里面的地址值是一样的,但是pa存放的是int,而pb存放的是float型,虽然他们指向同一个空间a,但是不同的是,当使用pb取使用空间变量a的时候,会以float型的空间大小和数据存储结构来使用a的值。

Q2

float a = 13.5;
double *pa = (double)&a;
//只是读取空间内容的话,不会引起严重错误
double b = *pa;
//如果是写的话,很有可能会引起严重错误
*pa = 345.45;

​ a的空间只有四个字节,但是pa以double的形式指向了空间a。通过*pa取读取a的空间值13.5时,除了会读取空间a的四个字节,还会读取空间a后面紧跟的4个字节。如果是写入新数据的话,除了前面4个字节会被写之外,后面紧跟的其他空间的四个字节也会被修改,这会引起严重的错误。所以对于指针变量做强制转换时,多数情况只会讲引用空间缩小,而不会将空间扩大。

Q3

int a = 125;
float *pa =NULL;
float b;

pa = (float *)&a;
float b = *pa;
//打印结果是乱码
printf("%f\n",b);

​ a和b的空间大小虽然都是个字节,a里面的125是按照整型存储的,但是通过*pa在读取a内容的时候,是按照float进行读取的,结果显然不对。

summary of three Q

​ 对于指针本身的强制类型转换,修改的是对指向空间的引用方式 ,这个过程必须小心,防止引用到别的空间,导致内存越位操作,或者数据访问导致乱码。

指针变量的空间

​ 1.同一种编译器环境下,一个指针变量所占用的内存空间是固定的。比如,在16位编译器下,任何一个指针变量都只占用2个字节,并不会随所指向变量的类型而改变

数据类型16位编译器32位编译器64位编译器
char111
void *248

​ 2. 既然每个指针变量所占用的内存空间是一样的,而且存储的都是地址,为何指针变量还要分类型?而且只能指向一种类型的变量?比如指向int类型的指针、指向char类型的指针。

int i = 2;
char c = 1;
char *p = &c;
printf("%d", *p);

​ 这里输出的结果是1,如果把第三行代码改成 int *p = &c; 输出结果是513

​ 原因:根据变量的定义顺序,这些变量在内存中大致分布如下

变量地址存储的内容
pffc1/ffc2ffc3
cffc30000 0001
iffc4/ffc5ffc4:0000 0010 ffc5:0000 0000

​ 其中,指针变量p和int类型变量i各占2个字节,char类型的c占一个字节,p指向c,因此p值就是c的地址

​ 最初的时候,我们用char *p指向变量c。当利用 *p 来获取变量c的值时,由于指针p知道变量c是char类型的,所以会从ffc3这个地址开始读取1个字节的数据:0000 0001,转为10进制就是1

​ 后来,我们用int *p指向变量c。当利用 *p 获取变量c的值时,由于指针p认为变量c是int类型的,所以会从ffc3这个地址开始读取2个字节的数据:0000 0010 0000 0001,转为10进制就是513

地址的强制转换

Q1

struct Test
{
    int Num;
    char *pcName;
      short sDate;
    char cha[2];
    short sBa[4];
}*p;

​ 设p的值为0x100000, 如下表达式的值分布为多少

p + 0x1 = 0x_?
(unsigned long) p + 0x1 = 0x_?
(unsigned int*)p + 0x1 = 0x_?

​ 指针变量与一个整数相加减并不是用指针变量里的地址直接加减这个整数。这个整数的单位不是byte 而是元素的个数

​ p + 0x1 的值为0x100000+sizof(Test)*0x1。至于此结构体的大小为20byte,所以p +0x1 的值为:0x100014。

​ (unsigned long)p + 0x1 的值呢?这里涉及到强制转换,将指针变量p 保存的值强制转换成无符号的长整型数。任何数值一旦被强制转换,其类型就改变了。所以这个表达式其实就是一个无符号的长整型数加上另一个整数。所以其值为0x100001。

​ (unsigned int)p + 0x1 的值呢?这里的 p 被强制转换成一个指向无符号整型的指针。所以其值为:0x100000+sizof(unsigned int)0x1,等于0x100004。

Q2

int main()
{
    int a[4]={1,2,3,4};
    int *ptr1 = (int *)(&a+1);
    int *ptr2 = (int *)((int)a+1);
    printf("%x,%x",ptr1[-1],*ptr2);
    return 0;
}

ptr1:将&a+1 的值强制转换成int类型,赋值给int 类型的变量ptr,ptr1 肯定指到数组a 的下一个int 类型数据了。ptr1[-1]被解析成*(ptr1-1),即ptr1 往后退4 个byte。所以其值为0x4。

​ ptr1:将&a+1 的值强制转换成int类型,赋值给int 类型的变量ptr,ptr1 肯定指到数组a 的下一个int 类型数据了。ptr1[-1]被解析成*(ptr1-1),即ptr1 往后退4 个byte。所以其值为0x4。

​ ptr2:按照上面的讲解,(int)a+1 的值是元素a[0]的第二个字节的地址。然后把这个地址强制转换成int类型的值赋给ptr2,也就是说ptr2 的值应该为元素a[0]的第二个字节开始的连续4 个byte 的内容。

  • 6
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C/C++中的强制转换(type casting)是将一个数据类型转换为另一个数据类型的过程。它可以通过将一个表达式强制转换为另一种类型来实现。强制转换可以帮助我们在某些情况下,将一种数据类型转换为另一种数据类型,以满足特定的需求。 强制转换有三种方式:C风格的强制转换、函数式的强制转换和静态类型转换。下面分别介绍。 1. C风格的强制转换 C风格的强制转换使用圆括号,将需要转换的数据类型放在圆括号中,并在前面添加一个转换类型的关键字。例如,在将一个浮点数转换为整数时,可以使用以下强制转换: ``` float f = 3.14; int i = (int)f; ``` 这将强制将浮点类型的f转换为整数类型的i。 2. 函数式的强制转换 函数式的强制转换使用以下语法: ``` type_name(expression) ``` 其中,type_name是要转换成的数据类型,expression是要转换的表达式。例如: ``` float f = 3.14; int i = int(f); ``` 这将强制将浮点类型的f转换为整数类型的i。 3. 静态类型转换 静态类型转换使用以下语法: ``` static_cast<type_name>(expression) ``` 其中,type_name是要转换成的数据类型,expression是要转换的表达式。例如: ``` float f = 3.14; int i = static_cast<int>(f); ``` 这将强制将浮点类型的f转换为整数类型的i。与函数式的强制转换相比,静态类型转换在编译时会进行类型检查,可以避免一些类型转换错误。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值