C++指针之对未声明的地址进行访问
2011-03-22 12:10
471 查看
例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;
这样就是为一个指定的内存地址赋值。
下列代码的运行结果是什么?
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;
这样就是为一个指定的内存地址赋值。
相关文章推荐
- 指针之对未声明的地址进行访问
- 通过指针访问值之程序声明一个指针和一个变量,然后输出它们的地址和它们所含的值
- C_C++_二维数组与二维指针的地址与访问关系
- 对一个未做声明的地址进行访问
- c++指针访问小结
- C++中,函数声明时指针、引用相关的语义,定义方法原型时参考。
- C++编程入门系列之二十七(数组、指针和字符串:指针变量的声明、地址相关运算--“*”和“&”)
- 实战c++中的智能指针unique_ptr系列--通过unique_ptr对shared_ptr进行初始化
- C/C++中关于地址、指针和引用变量的学习笔记(二) : 数组
- C/C++中关于地址、指针和引用变量的学习笔记(五) : 指针
- C/C++ 二维数据 静态动态声明和初始化及访问方法实例
- 理解C++中复杂的指针声明
- C++中使用内存映射文件存取struct,并用指针访问
- C++二维数组,指针常量与常量指针、常量参数传递、常量变量存储地址
- C/C++学习(4)函数与指针取地址符
- c++中如何通过函数参数对指针进行赋值
- 详解C++中的成员访问运算符和指针到成员运算符
- C++中cout输出字符型指针地址值的方法
- 第10章 指针(三)对地址进行分类------指针类型
- 函数交换,通过指针访问地址