例1、
下列代码的运行结果是什么?
int *ptr;
ptr=(int *)0x8000;
*ptr=3;
解答:指针问题,首先将指针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;
这样就是为一个指定的内存地址赋值。