句柄与指针的区别(一)

内存句柄与指针的区别

句柄其实就是指针,但是他和指针最大的不同是:给你一个指针,你可以通过这个指针做任何事情,也许是好事,也许是通过这个指针破坏内存,干一些捣乱的事情。这个我想大家都会碰到过,因为乱用指针导致程序崩溃
    句柄就没有这个缺点,通过句柄,你只能干一些windows让你干的事情(调用一些api函数等等),没有了指针的坏处。

句柄是一些表的索引也就是指向指针的指针,句柄和指针都是地址,句柄是Windows编程的一个关键性的概念,编写Windows应用程序总是要和各种句柄打交道。
    所谓句柄,就是一个唯一的数,用以标识许多不同的对象类型,如窗口、菜单、内存、画笔、画刷等。在Win32里,句柄是指向一个“无类型对象”(void*)的指针,也就是一个4字节长的数据。
    无论它的本质是什么,句柄并不是一个真正意义上的指针。从构造上看,句柄是一个指针,尽管它没有指向用于存储某个对象的内存位置。事实上,句柄指向一个包含了对该对象进行的引用的位置。
    句柄的声明是这样的:
    typedef void *HANDLE
    由于Windows是一个多任务操作系统,它可以同时运行多个程序或一个程序的多个副本。这些运行的程序称为一个实例。为了对同一程序的多个副本进行管理,Windows引入了实例句柄。Windows为每个应用程序建立一张表,实例句柄就好象是这张表的一个索引。
    不同在于:
      1、句柄所指的可以是一个很复杂的结构,并且很有可以是与系统有关的,比如说上面所说的线程的句柄,它指向的就是一个类或者结构,他和系统有很密切的关系,当一个线程由于不可预料的原因,而终止时在系统就可以回它所占用的资料,如CPU,内存等等,反过来想可以知道,这个句柄中的某一些项,是与系统进行交互的。由于Windows系统,是一个多任务的系统,它随时都可能要分配内存,回收内存,重组内存。
      2、指针它也可以指向一个复杂的结构,但是通常是用户定义的,所以的必需的工作都要用户完成,特别是在删除的时候。但在VC++6.0中也有一些指针,它们都是处理一些小问题才用的,如最常见的字符的指针,它也是要用户处理的如果你动态分配了内存;但是Cstring 就不要用户处理了,它其实是VC++中的一个类,所以的操作都由成员函数完成,产生(分配)由构造函数,删除(回收)由析构函数完成。

获得窗口句柄三种方法

.HWND FindWindow(LPCTSTR lpClassName, LPCTSTR lpWindowName)

HWND FindWindowEx(HWND hwndParent, HWND hwndChildAfter,LPCTSTR lpClassName, LPCTSTR lpWindowName)

2.HWND WindowFromPoint(POINT& Point)//获得当前鼠标光标位置的窗口HWND

3.BOOL CALLBACK EnumChildProc(HWND hwnd,LPARAM lParam)

BOOL CALLBACK EnumChildWindows(HWND hWndParent, WNDENUMPROC lpEnumFunc,LPARAM lParam)
BOOL CALLBACK EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam)
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)

指针 句柄之间的转换

a.由指针获得句柄
CWnd * pWnd;
CWnd HWnd;
HWnd = pWnd->GetSafeHWnd();

b.由句柄得到指针:
CWnd* pWnd=FromeHandle(hMyHandle);
pWnd->SetWindowText("Hello World!");
or CWnd* pWnd; pWnd->Attach(hMyHandle);

MFC类中有的还提供了标准方法,比如Window 句柄:
static CWnd* PASCAL FromHandle( HWND hWnd );
HWND GetSafeHwnd( ) const;

对于位图:
static CBitmap* PASCAL FromHandle( HBITMAP hBitmap );
static CGdiObject* PASCAL FromHandle( HGDIOBJ hObject );
HGDIOBJ GetSafeHandle( ) const;

有人说句并就是一个标示,一个ID号,是错误的。一个ID号可以包括多个资源,比如说单文档中的IDR_MAINFRAME,一般是指在硬盘上的资源。但是当把硬盘上的资源调入内存以后,将有一个句柄指向它,但是句柄只能指向一个资源。而且句柄知道所指的内存有多大。还有指针,指针指向地址,它不知道分配的内存有多大。
    但是如果你定义一个句柄,然后在VC里面右击鼠标,选择"go to definition of HANDLE,你会发现它的本质就是一个指针,但是它的作用不同于指针。

句柄是个指针,指向一块内存,但至于这块内存跟句柄所标识的对象是怎么联系起来的,调用者不需要清楚,调用者只需要知道,这个句柄联系着一个win32对象。
    句柄是物理地址,可以跨进程传递,例如,HANDLE ha进程A的一个窗口,你可以在进程B中利用一个跟ha相等的值(相等就是说它们强制转成int32的值相等)初始化一个句柄,利用这个句柄你可以对进程 A的那个对象进行操作,例如MoveWindow,ShowWindow等。
    句柄包含了一些引用计数之类的东西,所以我的上一点说的给句柄赋值是不安全的,Windows API提供了一些函数,可以对句柄进行操作。

句柄就是受限的指针
    它是由操作系统管理的,你不能通过它存取操作系统创建的数据结构

操作系统在创建一个对象(如GDI, FILE)等的时候,它会为这个对象CONTEXT保留一块数据结构,然后把它放在一张全局表中。。句柄就是这块数据结构在表中的索引

指针对应着一个数据在内存中的地址,得到了指针就可以自由地修改该数据。Windows并不希望一般程序修改其内部数据结构,因为这样太不安全。所以 Windows给每个使用GlobalAlloc等函数声明的内存区域指定一个句柄(本质上仍是一个指针,但不要直接操作它),平时你只是在调用API函数时利用这个句柄来说明要操作哪段内存。当你需要对某个内存进行直接操作时,可以使用GlobalLock锁住这段内存并获得指针来直接进行操作。
    lshgao的意见:
    句柄是指针的“指针”,使用句柄主要是为了利于windows在进程内存地址空间移动分配的内存块,以防止进程的内存空间被撕的四分五裂而存在过多的碎片。
    
    阿城的意见:
    句柄是一些表的索引也就是指向指针的指针。间接的引用对象,windows可以修改对象的"物理"地址和
    描述器的值,但是句柄的值是不变的。
    
    刘志用的意见:
    句柄和指针都是地址,不同在于:
    1,句柄所指的可以是一个很复杂的结构,并且很有可以是与系统有关的,比如说上面所说的线程的句柄,它指向的就是一个很类或者结构,他和系统有很密切的关系,当一个线程由于不可预料的原因,而终止时在系统就可以回它所占用的资料,如CPU,内存等等,反过来想可以知道,这个句柄中的某一些项,是与系统进行交互的。由于Windows系统,是一个多任务的系统,它随时都可能要分配内存,回收内存,重组内存。
    2,指针它也可以指向一个复杂的结构,但是通常是用户定义的,所以的必需的工作都要用户完成,特别是在删除的时候。
    但在VC++6.0中也有一些指针,它们都是处理一些小问题才用的,如最常见的字符的指针,它也是要用户处理的如果你动态分配了内存;但是Cstring 就不要用户处理了,它其实是VC++中的一个类,所以的操作都由成员函数完成,产生(分配)由构造函数,删除(回收)由析构函数完成。
    
    zjf问:
    你好,我在学习用vc++6.0编译多线程程序中遇到了很多句柄,但是不明白他的具体作用以及如何使用句柄,希望您能给我举几个具体实例,不甚感激!
    比如说: HANDLE hThread,它是怎样具体使用的?
    答:你使用CreateThead后函数会返回一个句柄,它代表这个线程。你可能会调用SetThreadPriority去修改线程的优先级,使用 ResumeThread去重新开始一个线程的运行,在调用这些函数时你都需要告诉系统你到底要操作哪个线程,而刚才返回的句柄派上用处了,这些函数的第一个参数就是线程的句柄。
    看VC中总是出现这个句柄的概念,以前一直以为就是指指针,但是越看越觉得不是这么简单,于是本着有问题百度一下的原则,看到如下解释,很是经典:

csdn上有人说过:牧童遥指杏花村。
    牧童的手为指针,杏花村的牌子为句柄,杏花村酒店为对象的实例.

句柄就是烤叉,用烤炉烤过鸭,鸡,牛,羊,狗么?
    炉子里的东西是看不见,摸不到的,但你能用叉子去控制,至于叉子上的是什么,你放进去前应该记住。呵呵

句柄有时是指针,有时是索引,但他绝对是一把钥匙,内核句柄110的钥匙,GDI句柄是您的钥匙,只对您有效。

单从概念上讲,句柄指一个对象的标识,而指针是一个对象的首地址。从实际处理的角度讲,即可以把句柄定义为指针,又可以把它定义为同类对象数组的索引,这两种处理方法都有优缺点,至于选用哪种方式,完全应该看实际需要,这可以说是一种程序设计上的技巧。那种单纯认为句柄是指针或索引的想法都是机械的、不确切的。其实,在Windows中类似的处理是很多的、很灵活的。再具个相似的例子:

我们知道,在Windows中有个函数叫做CallWindowProc。
    故名思义,它的作用就是向指定的窗口过程传递一个消息。你也许会想,既然我已经有了窗口过程的指针,为什么我不可以直接通过这个指针调用该函数(这是C语言的内建功能)?事实上,在Win16中确实可以这么做,因为GetWindowLong返回的确实是该函数的指针。但在Win32 下,GetWindowLong返回的并不是该函数的指针,而是一个包含函数指针的数据结构的指针(MSDN上说返回的是一个窗口函数地址或它的句柄,就是指的这种情况)。该数据结构是可变的,但只要你使用CallWindowProc来调用的话是不会出错的。这里我们又看到使用句柄处理带来的好处。(补充说明一点:微软在这里之所以这么处理,是为了解决16位/32位以及ANSI/UNICODE的转化问题)

看来,句柄很多时候是一个用于描述和标记一个资源的数据结构的指针,而不是资源本身的指针,句柄中可能包含资源的指针,但是根多时候不仅仅是这样。

本文转自:http://xuejianxinokok.blog.163.com/blog/static/4043757720099301341319/

http://blog.csdn.net/wangningyu/article/details/4943184

时间: 2024-10-11 23:46:14

句柄与指针的区别(一)的相关文章

句柄和指针的区别和联系

所谓 句柄实际上是一个数据,是一个Long (整长型)的数据.句 柄是WONDOWS用来标识被应用程序所建立或使用的对象的唯一整数,WINDOWS使用各种各样的句柄标识诸如应用程序实例,窗口,控制,位图,GDI对象等等.WINDOWS句柄有点象C语言中的文件句柄. 从上面的定义中的我们可以看到,句柄是一个标识符,是拿来标识对象或者项目的,它就象我们的姓名一样,每个人都会有一个,不同的人的姓名不一样,但是,也可能有一个名字和你一样的人.从数据类型上来看它只是一个16位的无符号整数.应用程序几乎总是

句柄与指针的区别(二)

句柄vs指针     句柄是一种指向指针的指针.我们知道,所谓指针是一种内存地址.应用程序启动后,组成这个程序的各对象是住留在内存的.如果简单地理解,似乎我们只要获知这个内存的首地址,那么就可以随时用这个地址访问对象.但是,如果您真的这样认为,那么您就大错特错了.我们知道,Windows是一个以虚拟内存为基础的操作系统.在这种系统环境下,Windows内存管理器经常在内存中来回移动对象,依此来满足各种应用程序的内存需要.对象被移动意味着它的地址变化了.如果地址总是如此变化,我们该到哪里去找该对象

句柄和指针

有关句柄和指针的常用函数 1. 如何获取应用程序的 实例句柄? AfxGetInstanceHandle()    应用程序的 实例句柄保存在CWinAppIm_hInstance 中,可以这么调用 AfxGetInstancdHandle获得句柄.      Example: HANDLE hInstance=AfxGetInstanceHandle(); 2. 如何通过代码获得应用程序主窗口的 指针? AfxGetMainWnd  GetSafeHwnd() AfxGetAppName() 

[转载]从GetSafeHwnd()和GetSafeHandle()分析句柄和指针

GetSafeHwnd()和GetSafeHandle()的主要区别: 1.使用者不同: (1)窗体使用: GetSafeHwnd()用于获取窗体的安全句柄(即HWND),有了HWND我们就可以方便的对HWND指向的窗体进行所需的操作了: (2)GDI对象使用: GetSafeHandle(),用于获取GDI对象的句柄. 注意:在使用指针时强烈建议这么做: // pSomeWnd 为一个窗体的指针 if ( NULL != pSomeWnd && NULL != pSomeWnd->

Windows中句柄和ID的区别

VC++菜单的句柄也可以理解成菜单的识别符(ID). 但如果指菜单项的ID, 那可能又是一回事了.按我的理解:  1. 句柄是程序运行中系统为其分配的,菜单项ID是编程者自己定义指定的.一般可在资源文件中定义也可在动态创建菜单时指定,程序中引用.  2. 菜单的句柄是属于菜单的,菜单项ID是属于菜单中某一个菜单项的.编程者通过菜单的句柄访问菜单,通过ID进行菜单项识别并进行消息处理.  3. 菜单的句柄类型是HMENU, 菜单项ID的类型是UINT(无符号整型).当然这两种类型本质上并无差别,但

指针数组和数组指针的区别

数组指针(也称行指针)定义 int (*p)[n];()优先级高,首先说明p是一个指针,指向一个整型的一维数组,这个一维数组的长度是n,也可以说是p的步长.也就是说执行p+1时,p要跨过n个整型数据的长度. 如要将二维数组赋给一指针,应这样赋值:int a[3][4];int (*p)[4]; //该语句是定义一个数组指针,指向含4个元素的一维数组. p=a;        //将该二维数组的首地址赋给p,也就是a[0]或&a[0][0] p++;       //该语句执行过后,也就是p=p+

引用与指针的区别

引用:相当于给一个变量取的别名,它本身不是一种数据类型,因此不战用存储空间,不能建立数组的引用 引用作为函数参数:当发生函数调用时,用引用作为参数,在内存中并不会产生实参的副本,也不会给引用这个形参分配空间, 而是直接对实参进行操作,但如果用一般变量作为函数参数,则会给它分配空间,并且作为实参的副本,如果 传递的是对象,还将调用拷贝构造函数 引用与指针的区别:相同点:引用与指针都会导致实参对象值的改变 不同点:a.引用不用分配空间,指针要分配空间,且指针作为形参在调用时,必须用变量的地址作为实参

指针数组??数组指针的区别.xml

pre{ line-height:1; color:#1e1e1e; background-color:#f0f0f0; font-size:16px;}.sysFunc{color:#627cf6;font-style:italic;font-weight:bold;} .selfFuc{color:#800080;} .bool{color:#d2576f;} .condition{color:#000080;font-weight:bold;} .key{color:#000080;} .

引用和指针的区别

引用(references)使用"."操作符,指针(pointers)使用"*"和"->"操作符,这是两者最基本也是最熟悉的区别了,应该不用详说. 首先,没有所谓的null reference.一个reference必须总代表某个对象,因此C++要求references必须有初值: string& rs://错误!references必须被初始化 string s("xyzzy"); string& rs