15. 指针1

  1. 任何时候指针只能有两种状态,NULL状态和正常状态。
  2. 仅仅给出地址,计算机无法正确有效地读写数据。
  3. 指针是一个具有解释方式信息的地址

 

分析指针时关心两件事:

1.在哪里

2.是什么

理解了指针的解释方式,就可以任意解释内存中的数据

举例:

unsigned char *p = NULL;

int n = 999;

int ary[] = { 1,2,3 };//数组名是数组第0个元素类型的指针常量

p = (unsigned char *)&n;

printf("%X\n", n);   //直接访问,按变量自身的类型,输出3E7

printf("%X\n", p[0]);//间接访问,按指针定义时的类型,输出E7

 

 

指针的运算:

type *ptr = ...

int n = ...

ptr[n] = *(type *)((int)ptr + sizeof(type) * n)

 

1.对指针做下标运算,得到指针定义时类型的变量:

int *p = NULL;

int n = 3;

printf("%X\n", &p[n]);//获取的是地址,不会访问p[n],所以不会引发异常,输出C

printf("%X\n", p[n]); //会访问p[n], 会引发异常

 

2.对指针做加法运算,必须加整数类型,得到同类型的指针常量:

ptr + n = (type * const)((int)ptr + sizeof(type) * n)

2.1 const限定符

int const *ptr = ary;//const在*左边的,间接访问的目标是常量,不能间接写入

int *const ptr = ary;//const在*右边的,指针自身是常量,指针变量不能修改

 

3.对指针做减法运算,必须减同类型指针,得到整形常量:

type *ptrA = ...

type *ptrB = ...

ptrA - ptrB = ((int)ptrA - (int)ptrB) / sizeof(type)

修改一个字节改变内存属性:

const char g_szText[] = "Hello11";

int main() {

char szBuff[] = "Hello World";

const char *psz = "Hello World";

puts(szBuff);

puts(psz);

puts(g_szText);

char *p = (char *)psz;

p[0] = '1';

p = (char *)g_szText;

p[0] = '2';

getchar();

return 0;

}

正常编译以上代码,可以观察到&g_szText和psz很近。但是继续运行会崩溃,因为改写了只读区的数据。

 

 

打开磁盘中的exe文件,找到.rdata,两行半的位置最后有一个字节404写为二进制是

0  1  0  0

w  r  e  s

四个字母代表WriteReadExecuteShare

 

 

改为1100,即C,内存属性变为可读可写。

 

 

再次调试,发现可以修改了,程序也没崩溃。

 

 

 

猜你喜欢

转载自www.cnblogs.com/Nutshelln/p/12743718.html