指针地址的强制转换(一)

0x01:引入指针地址强转概念

从下面这个例子引入强制转换的概念:

struct test{
	char string[2];  //2
	int *point;   //4
	int nu[2];    //8
	short data[3];  //6
}*p;

如果p 的值为0x100000。如下表表达式的值分别为多少?

p + 0x01 = 
(unsigned long)p + 0x01 = 
(unsigned int*)p + 0x01 =

0x02:分析实例

主要的原理还是在前面一篇文章有说到,表达式“a+1”与“&a+1”之间的区别,同理,指针变量与一个整数相加减并不是用指针变量里的地址直接加减这个整数。这个整数的单位不是byte 而是元素的个数。
Q1: p + 0x1 的值为0x100000+sizof(test)0x1。至于此结构体的大小为20byte,所以p +0x1 的值为:0x100014;
Q2: (unsigned long)p + 0x1 的值呢?这里涉及到强制转换,将指针变量p 保存的值强制转换成无符号的长整型数。任何数值一旦被强制转换,其类型就改变了。所以这个表达式其实就是一个无符号的长整型数加上另一个整数。所以其值为:0x100001;
Q3:(unsigned int
)p + 0x1 的值呢?这里的p 被强制转换成一个指向无符号整型的指针。所以其值为:0x100000+sizof(unsigned int)*0x1,等于0x100004;

0x03:实例解析

实例代码:

//point.c
#include <stdio.h>
int main()
{
	int a[4] = {1,2,3,4};

	int *p1 = (int *)(&a+1);
	int *p2 = (int *)((int)a+1);

	printf("The a address is %p\n",&a);
	printf("The a+1 address is %p\n",&(a[1]));
	printf("The (int)a address is %p\n",(int)a);
	printf("The (int)a+1 address is %p\n",(int)a+1);
	printf("%x %p\n",p1[-1],p2);

	return 0;
}

Linux 环境下使用GCC进行编译:

curtis@curtis-virtual-machine:/mnt/hgfs/share/write_code/c_test$ gcc point.c 
point.c: In function ‘main’:
point.c:57:20: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
  int *p2 = (int *)((int)a+1);
                    ^
point.c:57:12: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
  int *p2 = (int *)((int)a+1);
            ^
point.c:61:38: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
  printf("The (int)a address is %p\n",(int)a);
                                      ^
point.c:61:2: warning: format ‘%p’ expects argument of type ‘void *’, but argument 2 has type ‘int’ [-Wformat=]
  printf("The (int)a address is %p\n",(int)a);
  ^
point.c:62:40: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
  printf("The (int)a+1 address is %p\n",(int)a+1);
                                        ^
point.c:62:2: warning: format ‘%p’ expects argument of type ‘void *’, but argument 2 has type ‘int’ [-Wformat=]
  printf("The (int)a+1 address is %p\n",(int)a+1);

输出结果:

curtis@curtis-virtual-machine:/mnt/hgfs/share/write_code/c_test$ ./a.out 
The a address is 0x7ffe7e4ddd20
The a+1 address is 0x7ffe7e4ddd24
The (int)a address is 0x7e4ddd20
The (int)a+1 address is 0x7e4ddd21
4 0x7e4ddd21

0x04:结果分析
p1:将&a+1 的值强制转换成int类型,赋值给int 类型的变量p,p1 肯定指到数组a 的下一个int 类型数据了。p1[-1]被解析成*(p1-1),即p1 往后退4 个byte。所以其值为0x4。
p2:按照上面的讲解,(int)a+1 的值是元素a[0]的第二个字节的地址。然后把这个地址强制转换成int类型的值赋给p2,也就是说p2 的值应该为元素a[0]的第二个字节开始的连续4个byte 的内容。

  • 5
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值