老码识途1之理解指针和指针强制转换

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_29983883/article/details/102757830

我们都知道指针用来存储内存的地址,而内存地址一般32位机器上是32位bit,64位机器上64位bit,但是当我们在运行下面的代码时,编译时为什么会报错,,大家可能想到的就是类型不对,那么,现在又有一个问题来了,编译器怎么知道类型不对,明明指针内存大小空间要么是32位,要么是64位,现在怎么就出现这种报错

	int a  =12;
	short *p = &a;

下图是我运行的截图,实实在在的报了错
在这里插入图片描述
所以,由此可以推测指针变量应该包含两种信息:地址和指针类型,例如向下结构体

struct pointer{
long addresss;
int type;
}

指针为什么需要存储类型呢,这个关乎到读写变量的长度,没有存储在指针变量中,位于用该指针读写时mov指令中(mov指令是汇编指令),不同的读写长度对应着mov指令不同

	int a ;
	int *p = &a;
	* p = 32;
	char c;
	char *s = &c;
	*s = 'd';

下面是上面的语句的反汇编,在p = 32时,他的汇编指令是mov dword ptr [eax],20h,使用dword,一次写入4字节,在s = ‘d’上,汇编指令是mov byte ptr [eax],64h,使用的byte,一次写入1字节。

int a ;
int *p = &a;
002143BB mov dword ptr [p],eax
* p = 32;
002143BE mov eax,dword ptr [p]
002143C1 mov dword ptr [eax],20h
char c;
char *s = &c;
002143C7 lea eax,[c]
002143CA mov dword ptr [s],eax
*s = ‘d’;
002143CD mov eax,dword ptr [s]
002143D0 mov byte ptr [eax],64h

下图是p的内存存储的内容,也就是a的地址
在这里插入图片描述
下图就是a的内存,由上下两个图可以看出,a的地址地位存在低地址,高位存在高地址,所以我的电脑是小端对齐
在这里插入图片描述

下面就来说说指针强制转换吧;

	int a ;
	int *p = &a;
	* p =0x3244;
	char c;
	char *s = &c;
	*s = 'a';
    //交换两个指针所指对象,重新赋值
	char * n = s;

	s = (char *)p;
	*s = 'a';
	p = (int *)n;
	*p = 0x3244;

下面是反汇编

int a ;
int *p = &a;
001943B8 lea eax,[a]
001943BB mov dword ptr [p],eax
* p = 0x3244;
001943BE mov eax,dword ptr [p]
001943C1 mov dword ptr [eax],3244h
char c;
char *s = &c;
001943C7 lea eax,[c]
char c;
char *s = &c;
001943CA mov dword ptr [s],eax
*s = ‘d’;
001943CD mov eax,dword ptr [s]
001943D0 mov byte ptr [eax],64h
char * n = s;
001943D3 mov eax,dword ptr [s]
001943D6 mov dword ptr [n],eax
s = (char *)p;
001943D9 mov eax,dword ptr [p]
001943DC mov dword ptr [s],eax
*s = ‘d’;
001943DF mov eax,dword ptr [s]
001943E2 mov byte ptr [eax],64h ;即使现在s所指int对象内存,但是还是使用byte进行操作
p = (int *)n;
001943E5 mov eax,dword ptr [n]
001943E8 mov dword ptr [p],eax
*p = 0x3244;
001943EB mov eax,dword ptr [p]
001943EE mov dword ptr [eax],3244h 即使现在p所指char对象内存,但是还是使用dword进行操作

下面是交换前的内存情况,我们知道p = &a = 0x0135FD04,
在这里插入图片描述
这个图是执行完s = (char *)p;*s = 'd';发现a内存的四字节只有第一个字节内容发生了变化,后面三个都没有,
在这里插入图片描述
s= &c = 0x0135FCEF,
在这里插入图片描述
在这里插入图片描述
上图是由于执行p = (int *)n;*p = 0x3244;后,p所指对象是c的地址,即使c的内存空间只有1字节,但是mov按照4字节修改了c的内存,在这里,实际已经算是越界了,把c内存后面的三个字节的值都改变了,这是大大的bug,所以以后使用指针时,这里要特别消息,不然就越界了

猜你喜欢

转载自blog.csdn.net/qq_29983883/article/details/102757830