全域和局部函數,全域局部函數

來源:互聯網
上載者:User

全域和局部函數,全域局部函數

全域和局部函數  

         全域和局部函數是為了支援16bit的程式移植,或者是為了維護程式對16bit Windows的相容性。從32bit Windows起,全域函數和局部函數的實現是封裝一個相關的堆函數,這個堆函數用進程的預設堆的控制代碼。因此全域和局部函數比其它記憶體管理函數開銷更大。

       堆函數比全域和局部函數提供更多的特徵和控制。新的程式應該使用堆函數除非文檔特別地指出應該使用全域或者局部函數。例如,一些Windows程式必須使用LocalFree來釋放分配的記憶體,並且全域函數在DDE(動態資料交換),剪下板函數,OLE資料對象上依然地被使用。

       Windows 記憶體管理不再像1 6bit Windows那樣單獨地提供局部堆,全域堆。因此全域和局部的函數族是等價多的,選擇哪一個只是個人偏好的問題。注意到從16bit分段儲存模式到32bit的虛擬儲存模式的變化讓許多相關的全域和局部的函數以及它們的選項變得沒有必要和無意義。例如,再也沒有near points,far points,因為局部和全域的函數都返回一個32bit的虛擬位址。

       通過GlobalAlloc和LocalAlloc函數分配的記憶體對象是私人的,提交頁面的讀寫訪問權不能被其它進程擷取。用GMEM_DDESHARE標記的GlobalAlloc函數來分配的記憶體不再像16bit Windows那樣是全域共用的了。這個值已經沒有效果,現在只是為了相容性。處於其它目的需要共用記憶體的應用程式必須使用檔案對應物件。多進程程式可以對同一個檔案對應物件映射來提供命名的共用的記憶體。

       記憶體配置是被限制在可用的實體記憶體,包括硬碟上的分頁檔。當你分配固定記憶體的時候,GlobalAlloc和LocalAlloc函數返回一個指標,調用的進程可以立即使用這個指標去訪問記憶體,當你分配一個可移動的記憶體,返回值是一個控制代碼(一個指向控制代碼表中條目的指標,但不是記憶體塊的首地址)。為了得到可移動記憶體對象,要使用GlobalLock和LocalLock函數。

       實際分配的記憶體大小可能大於請求的大小。為了確定實際分配的位元組數目,使用GlobalSize和LocalSize函數。如果實際分配記憶體的大小大於請求的,進程可以使用它們的所有。

       GlobalReAlloc和LocalReAlloc函數可以改變通過GlobalAlloc和LocalAlloc函數分配的記憶體的大小或者記憶體對象的屬性。記憶體大小可以增加或者減少。

       GlobalFree 和LocalFree函數釋放由GlobalAlloc和 LocalAlloc,或者GlobalReAlloc,LocalReAlloc函數分配的記憶體。為了丟棄指定的記憶體但是不使控制代碼作廢,可以使用GlobalDiscard和LocalDiscard函數。隨後控制代碼可以被GlobalReAlloc和LocalReAlloc使用去分配一個新的記憶體塊,用的是相同的控制代碼。

         為了返回指定記憶體對象的資訊,可以使用GlobalFlags或者LocalFlags函數。資訊包括記憶體對象的鎖定數目並且指明對象是否是可拋棄或者已經被拋棄。為了返回和指定指標相關的對象的控制代碼可以使用函數GlobalHandle和LocalHandle。


局部函數與全域函數的範圍各是什?

局部函數是只能在這個某個映像中使用的函數,如DLL裡面如果某一個函數沒有匯出,那麼這個函數就是這個DLL的私人函數(我習慣叫做私人函數了),這個函數只能在這個DLL中使用。而向kernel32.dll裡面那匯出的上千個API就是公有函數,這些函數不但能在DLL本身使用,也可以在別而PE檔案中使用。
 
問一下C++的局部函數與全域函數是什?

#include <iostream>
using namespace std;

int m=8;

void function()
{
int n=5;
cout<<m<<endl;
}

int main()
{
int a=10;
cout<<a<<endl;
function();
cout<<m<<endl;
return 1;
}

首先介紹一下變數吧,靜態變數等就不說了,只說比較一般常見的變數
變數,都是有其生命週期的,像人一樣出生,死亡
在一個函數裡聲明的變數,聲明的時候"出生"了,這個函數結束後它也跟著死亡了
而main()函數,它也是一個函數,但是是最主要的函數,因此叫main
一個程式執行的過程,就是從main()的第一行代碼執行到最後一行代碼

我們現在假設有個游標指著正在啟動並執行那一行代碼,現在示範一下程式啟動並執行過程
總是從main()開始的
main()裡4行代碼,
第一行a"出生"了(執行完最後一行return 1;則變數a的生命結束了)
第二行把a的值輸出
第二行執行function()
1.現在游標跳到function()函數的第一行int n=5;(局部變數n出生了,並且值為5)
2.繼續執行下一行代碼cout<<m<<endl;至此function()函數裡的代碼執行完畢了,這個函數被用完了,這個函數裡的局部變數n現在也死掉了(不存在了)
游標跳回到main()函數裡,
繼續執行下一行cout<<a<<endl;把a的值輸出
下一行,把全域變數m的值輸出
再執行下一行return 1;
至此main()函數也執行完畢,那麼main()裡的變數a也會被銷毀(可以看做是main函數裡的局部變數,main函數運行完了,這個變數也要消失了)
這就是程式啟動並執行過程,就是一條一條執行main函數的語句,這過程中可能會跳到別的地方去
總結:a是main()函數裡的變數,只在main裡有效,且壽命和main()函數是一致的,n是function函數裡的變數,只在function函數裡有效,
如在main函數裡操作n,或者在function函數裡操作a,都是錯誤的,而m被放在所有函數的外面,
它是全域變數,不是屬於某個函數的,所有函數都可以操作它,程式運行起來它就誕生,程式關閉了它消亡

至於子函數是否需要傳回值,則完全取決於自己的需要,看下面的程式,倆對比著看

-----------------------
函數的int function1(int n),在main裡執行int b=function1(a)這句話時,從main()裡跳到function1()函數裡,
並且function1()裡產生了一個局部變數n,接受了a的值5,現在function1()函數裡有個局部變數n=5;最後把值25return了回去,
25賦值給main函數裡的b;

#include <iostream>
using namespace std;

int function1(int n)
{
return n*n;
}

int main()
{
int a=5;
int b=function1(a);
cout<<b<<endl;
return 1;
}
--------------------
函數void......餘下全文>>
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.