指针之对未声明的地址进行访问

例1、

下列代码的运行结果是什么?

int *ptr;

ptr=(int *)0x8000;

*ptr=3;

解答:指针问题,首先将指针ptr指向一个指定的地址,即对一个未作声明的地址直接进行访问,所以访问出错。这块地址可能已经被用,或者被其他程序占用等,因此会导致错误。

 把这个地址0x8000给指针ptr ,但是这个地址不一定是空闲地址,有可能被其他的地方占用。这样就又可以导致访问错误。

总之 ,不能随意的给指针指定一个地址。

 

例2、

下面这个程序在哪一行会崩溃?

struct S

{

   int i;

   int *p;

};

int main()

{

  S s;

  int *p=&s.i;

  p[0]=4;

  p[1]=3;

  s.p=p;

  s.p[1]=1;

  s.p[0]=2;

  return 0;

]

解析:

首先&s.i的地址赋给p,即p指向了i的地址,所以p[0]即为i,p[1]即为S中p指向的地址,即p[1]为*(p+1),p又为

i的地址,所以i的地址加一个int就是p的地址,即&p,再解引用*(&p)即为p此时指向的地址。

所以p的值为0x00000003,

然后s.p=p;

因为p还是存放着i的地址,此时赋值,即s.p=&s.i;即s中的p指向了s中的i的地址。

s.p[1]=1;

等价于*(&s.i+1)即i的地址加上一个int,即为p的地址&p,然后解引用即为p指向的地址,所以这句意思即为,为s中的p指向的地址赋值为1,所以s中p的值为0x00000001,此时s中的p就不再指向s中的i的地址了。

最后:s.p[0]=2;

即为*(s.p),即为s中的*p赋值,意思就是在内存0x00000001的上面赋值为2,这样对于一个未作声明的地址直接进行访问,所以出错,即是在s.p[0]=2;这句中崩溃的。

 

如果将最后两句调换则最终是正确的,即

  s.p[0]=2;

  s.p[1]=1;

这样是意思是一开始s中的p还是指向s中的i的地址的,s.p[0]=2;这句的意思就是为s中的i赋值为2,因为此时p还是指向i的地址的。

s.p[1]=1;

这句即为*(&s.i+1)即为p指向的地址,将p指向的地址赋值为1,即p指向的地址为0x00000001;所以最后就不会出错。

 

总结:

这两个例子都是为一个指定的地址赋值,在一个不确定的地址上面进行直接访问,导致出错。如果在一个确定可以访问的地址上进行赋值也是正确的,比如:

 int *p = (int*)0x0018ff5c;
 *p = 3;
 std::cout<<*p<<std::endl;

在我机器上输出了3,说明这块内存是可以访问的,但是这块内存地址是不一定的,有的电脑上就有可能被占用。不过还有一种方式:

    int i;
    int m=(int)&i;
    int *ptr;
    ptr=(int *)m;
    *ptr=3;

这样就是为一个指定的内存地址赋值。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值