句柄與指針的區別(一)


內存句柄與指針的區別

    句柄其實就是指針,但是他和指針最大的不同是:給你一個指針,你可以通過這個指針做任何事情,也許是好事,也許是通過這個指針破壞內存,干一些搗亂的事情。這個我想大家都會碰到過,因為亂用指針導致程序崩潰
    句柄就沒有這個缺點,通過句柄,你只能干一些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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM