改变指针指向
来源:互联网 发布:手机怎么淘宝秒杀 编辑:程序博客网 时间:2024/05/20 14:27
http://blog.csdn.net/norains/article/details/6746844
如何通过函数来改变传入指针的指向?想必大家第一反应就是使用指向指针的指针作为形参,也就是说会写类似于Func_1的函数:
- void Func_1(DWORD **ppdw)
- {
- *ppdw = &g_dwVal;
- }
g_dwVal是一个全局变量,只要知道这个即可,其余的暂时不用考虑。有了Func_1,那么调用估计大家也会想到,无非是传入一个指针,如:
- pBuf = NULL;
- Func_1(&pBuf);
如果你认为这是C++通过函数改变指针指向的全部,那么你就太小看它了。使用"DWORD **"能改变指针的指向,那是不是通过"DWORD *"就不行了呢?答案是否定的,形参为"DWORD *"也可以改变指针指向!不过,这个函数的写法就有所不同,如Func_2:
- void Func_2(DWORD *pdw)
- {
- *(reinterpret_cast<DWORD *>(pdw)) = reinterpret_cast<DWORD>(&g_dwVal);
- }
函数写法不同,调用也要有所区别,如:
- pBuf = NULL;
- Func_2(reinterpret_cast<DWORD *>(&pBuf));
如果你测试过这段代码,那么会发现即使函数形参是"DWORD *",也可以改变指针的指向!
在这里再稍微多说一点,Func_2的函数体,其实写成这样也是可以正常赋值的,如:
- void Func_2(DWORD *pdw)
- {
- *(reinterpret_cast<DWORD **>(pdw)) = &g_dwVal;
- }
我们再来看一个更加有趣的问题,如果指针的类型是BYTE,那么是不是也能正常改变呢?所以,我们便有了一个Func_3函数:
- void Func_3(BYTE *pb)
- {
- *(reinterpret_cast<DWORD **>(pb)) = &g_dwVal;
- }
调用的时候,自然也是有所区别:
- pBuf = NULL;
- Func_3(reinterpret_cast<BYTE *>(&pBuf));
经过测试,这样的方式也是能够改变指针的指向的。估计看到这里,应该不少朋友迷惑了,为什么呢?在回答这个问题之前,我们继续再看另一个更有趣的问题,不通过指针,而是通过"DWORD"类型来改变指针的指向!于是,便有了函数Func_4:
- void Func_4(DWORD dwVal)
- {
- *(reinterpret_cast<DWORD *>(dwVal)) = reinterpret_cast<DWORD>(&g_dwVal);
- }
不用想,调用方式自然也是有区别,如:
- pBuf = NULL;
- Func_4(reinterpret_cast<DWORD>(&pBuf));
估计很多初学者看到这里,应该已经两眼发晕了吧?我们不妨看看为何可以改变的真正原因。
要明白上述函数为何能够正常改变指向,那么就必须明白指针的地址。对于指针的地址,它其实分为两部分,一部分是指针本身的地址,另一部分则是指针指向的地址。这样说可能大家有点糊涂,不妨看如下的图示:
如果是C++高手的话,那么对于这张图肯定是非常熟悉,但可能初学者就有点晕了。没事,我们现在一起来看看。
假设有个指针,名为pBuf。对于图中的0x4000 0000来说,这是指针本身的地址,以代码表示,便是&pBuf;而0x4000 0000这个内存地址存储的0x8000 0000,便是指针指向的地址,代码表示为pBuf;至于0x1234 5678,不用说,就是0x8000 0000这个内存块的数值了,代码自然是*pBuf。根据这些内容,不难得出这个表:
地址/数值
代码
0x4000 0000
&pBuf
0x8000 0000
pBuf
0x1234 5678
*pBuf
还是以图为例子,如果要改变指针的指向的话,那么只需要改变0x4000 0000这个内存里面的数值即可。明白这点,对于之前的函数理解就没什么难度了。大家不妨回头看看,其实在调用这些Func_x函数时,传入的都是"&pBuf",也就是指针本身的地址。既然已经知道了指针本身的地址,那么改变指针存储的值还有什么问题么?函数所做的,只不过是一些转换而已。
按理说,本文到此已经结束,但最后不妨再看一个初学者非常容易搞混的问题:空指针是否占据内存空间?也就是说,下面这行代码是否占据内存空间:
- DWORD *pBuf = NULL;
答案是占有空间!如果对此还有疑惑,那么看了下面这张图,相想必就非常明白了:
所谓的空指针,只不过是指向内存地址为0x0000 0000的指针而已,和别的指针并没有任何不同,所以肯定占用空间。
这里,应该还会有人迷惑,如果指向指针的指针为空,那么会不会占用空间呢?也就是说下面这行代码:
- DWORD **ppBuf = NULL;
答案还是占用空间!指向指针的指针说白了,还是指针,既然是指针就有自己本身的地址,所以肯定占用空间!所不同的是,指向指针的指针的存储空间存储的是所指向的指针的地址而已。如果以第一幅图为例子,稍微完善一下,那么便有如下图示:
最后,便是全部的代码,以供大家参考:
- #include "windows.h"
- DWORD g_dwVal = 0x100;
- void Func_1(DWORD **ppdw)
- {
- *ppdw = &g_dwVal;
- }
- void Func_2(DWORD *pdw)
- {
- *(reinterpret_cast<DWORD **>(pdw)) = &g_dwVal;
- //*(reinterpret_cast<DWORD *>(pdw)) = reinterpret_cast<DWORD>(&g_dwVal);
- }
- void Func_3(BYTE *pb)
- {
- *(reinterpret_cast<DWORD **>(pb)) = &g_dwVal;
- }
- void Func_4(DWORD dwVal)
- {
- *(reinterpret_cast<DWORD *>(dwVal)) = reinterpret_cast<DWORD>(&g_dwVal);
- }
- int _tmain(int argc, _TCHAR* argv[])
- {
- DWORD *pBuf = NULL;
- pBuf = NULL;
- Func_1(&pBuf);
- pBuf = NULL;
- Func_2(reinterpret_cast<DWORD *>(&pBuf));
- pBuf = NULL;
- Func_3(reinterpret_cast<BYTE *>(&pBuf));
- pBuf = NULL;
- Func_4(reinterpret_cast<DWORD>(&pBuf));
- return 0;
- }
- 改变指针指向
- 小议如何改变指针的指向
- 小议如何改变指针的指向
- 小议如何改变指针的指向
- 通过char **指针改变char*指针的指向
- 通过2级指针改变1级指针的指向
- 使用指向指针的指针改变一个传递进来的指针的指向!
- 数组缓冲区的溢出会改变指针指向?
- C++改变虚指针指向的虚表
- 向NULL地址COPY数据和不断改变指针指向
- 指向指针的指针**p改变*p值可以传递数值并且不改变p地址
- this指向,改变this指向
- 改变指针指向的地址为什么需要二维指针,从汇编角度分析
- 改变指针指向的字符内容、动态分配字符型指针变量内存空间
- C/C++ 子函数返回局部变量、指针 和改变指针指向
- 指针变量作为函数参数为了改变指针变量指向实参的值
- C语言二级指针做函数参数改变该指针的指向
- 指向指针的指针
- 配置Linux做网关
- 【小蒙淘金】4月8日-金评
- 代码中特殊的注释
- android超炫button按钮动画效果
- C语言 让我头晕的值传递与址传递
- 改变指针指向
- 今天的一下子跳出来了的超级玛丽
- 容器迭代器操作
- 架构设计:生产者/消费者模式
- trap catch signal
- hdu 1506 (dp) Largest Rectangle in a Histogram
- STRUTES2整合SPRING出现的问题
- android带索引和标题的listview
- jvmstat3.0工具的安装和使用