卖逼视频免费看片|狼人就干网中文字慕|成人av影院导航|人妻少妇精品无码专区二区妖婧|亚洲丝袜视频玖玖|一区二区免费中文|日本高清无码一区|国产91无码小说|国产黄片子视频91sese日韩|免费高清无码成人网站入口

作用域總結(jié)

MyMSDN 記錄開發(fā)新知道 導(dǎo)航?? ? ? ?? 新隨筆 聯(lián)系 聚合管理統(tǒng)計???? 隨筆 - 83 文章 - 1 評論 - 240 引用 - 0公告常用鏈接??? 我的隨筆 我的評論 我參與

MyMSDN 記錄開發(fā)新知道 導(dǎo)航

?

? ? ? ?

? 新隨筆 聯(lián)系 聚合管理

統(tǒng)計

?

?

?

? 隨筆 - 83 文章 - 1 評論 - 240 引用 - 0

公告

常用鏈接

?

?

? 我的隨筆 我的評論 我參與的隨筆

留言簿(10)

?

? 給我留言 查看公開留言

,

?

隨筆分類

?

? ?

?

? ? 隨筆檔案

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

文章檔案

?

相冊

,

? ? ?

搜索

?

?

積分與排名

?

? 積分 - 170362 排名 - 71

最新評論

?

?

?

?

?

?

?

? 評論內(nèi)容較長, 點擊標(biāo)題查看 ? 2. re: 什么是句柄?為什么會有句柄?HANDLE 好 --大俠 ? 3. re: 什么是句柄?為什么會有句柄?HANDLE 謝謝樓主,解釋的很好 --11 ? --顧 MSDN 上說這個函數(shù)IsWow64Process 在32位系統(tǒng)的dll 中也存在,我試驗了一下,WIN7 32位是有這個

函數(shù)IsWow64Process 的。

?

?

? 5. re: 什么是句柄?為什么會有句柄?HANDLE 化抽象為具體,深入淺出啊 --allen

?

閱讀排行榜 --paltan

?

?

?

?

? 2. 什么是句柄?為什么會有句柄?HANDLE(11837)

評論排行榜

? 1. 什么是句柄?為什么會有句柄?HANDLE(27)

,

?

?

?

? 4. C語言作用域、聲明以及定義(13)

作用域是一個在絕大多數(shù)(事實上我沒有見過沒有作用域概念的程序語言)程序語言的必然組成部分。日常良好的使用使用習(xí)慣和程序設(shè)計風(fēng)格,有時候讓我們漸漸忘記了這些作用域的準(zhǔn)確定義,因為它通常沒給我們帶來什么麻煩。這里我將其寫下來,僅在勾起大家模糊回憶中清晰的輪廓,也許有你所知的,也許有你所惑的,又或者可能我的理解和你的理解甚至格格不入,煩請大家積極指正。

幾個概念:

a. 外部變量,許多程序設(shè)計的書上用“全局變量”一詞,這里做一個統(tǒng)一,本文中“外部變量”就是所謂的“全局變量”。

b. 自動變量,許多程序設(shè)計的書上用“局部變量”一詞,這里做一個統(tǒng)一,本文中“自動變量”就是所謂的也可以稱作“動態(tài)局部變量”,與此相對的還有“靜態(tài)局部變量”,這兩種局部變量的并集就是通常所說的“局部變量”了。

這兩種叫法都是有其特定的道理和闡述的意義的。局部變量就是直言了其作用的范圍,它是局部的可見的(這一點您應(yīng)該深有體會)。因為在一個函數(shù)內(nèi)聲明一個變量,形如int a;它從它的聲明式開始,直到該函數(shù)的末尾(以“}”符號所標(biāo)識)有效。在函數(shù)體的外部,該變量a 不存在并且無效。這樣的聲明事實上是auto int a;聲明式的一種省略寫法,因此稱之為“自動變量”,因為它在該函數(shù)調(diào)用開始的時候初始化內(nèi)存空間,在調(diào)用結(jié)束的時候?qū)⑨尫旁摵瘮?shù)的內(nèi)存空間,而這一切不需要人工的干預(yù),因此它是自動的。

c. 靜態(tài)變量,又稱之為“靜態(tài)局部變量”,它通常與auto int a;的形式相反,它采用了static 關(guān)鍵字進(jìn)行修飾,static int a;。這樣的聲明導(dǎo)致了它在編譯時就分配了內(nèi)存空間,并在整個程序的運行過程中持續(xù)有效。唯一的限制是它僅在它所在的函數(shù)范圍內(nèi)有效。

1、外部變量的作用域從它聲明的位置開始,到其所在(待編譯)的文件的末尾結(jié)束。 參看以下代碼:

#include

#include

void extern1Processor(void );

int main(void ){

/*下面的語句因為extern1Variable 變量的定義在main 函數(shù)的后面

* 因此該函數(shù)將產(chǎn)生編譯錯誤。

* extern1Variable' undeclared (first use in this function)

printf("main.extern1Variable:dn",extern1Variable);*/

extern1Processor();

return EXIT_SUCCESS;

}

int extern1Variable = 2003;

,

/*下面能夠正確使用extern1Variable 變量,因為extern1Variable 的 * 定義在extern1Processor(void);方法之上。*/

void extern1Processor(void ){

printf ("extern1Processor.extern1Variable:dn",extern1Variable); }

2、如果要在外部變量的定義之前使用該變量,則必須在相應(yīng)的變量聲明中強(qiáng)制地使用關(guān)鍵字extern 。

參看以下代碼:

#include

#include

void extern2Processor(void );

int main(void ) {

extern int extern2Variable;

printf("extern2Processor.extern2Variable:dn",

extern2Variable);

extern2Processor();

return EXIT_SUCCESS;

}

int extern2Variable = 2004;

void extern2Processor(void ) {

printf("extern2Processor.extern2Variable:dn",

extern2Variable);

}

輸出結(jié)果:

extern2Processor.extern2Variable:2004

extern2Processor.extern2Variable:2004

3、如果外部變量的定義與變量的使用不在同一個源文件中,則必須在相應(yīng)的變量聲明中強(qiáng)制地使用關(guān)鍵字extern 。

假設(shè)在不同的源文件file1.c 與file2.c 中,我們都需要定義一個變量int aVariable = 2;時,分別編譯二者,它們將都包含一個變量aVariable 的聲明和定義。但是當(dāng)我們將它們一起加載的時候,由于它們都是外部變量,相同的變量名導(dǎo)致編譯器不知道它們的主次關(guān)系。因此,這里我們要求程序員一定要用extern 將主次分出來。比如file1.c 中int aVariable = 2;這句話聲明了aVariable 的類型為int ,為它分配了sizeof(int)內(nèi)存大小的一塊內(nèi)存空間,它的值為2。在file2.c 中我們聲明它extern int aVariable;(這里不能使用extern int aVariable=3;但是可以使用int aVariable;)這句話告訴了編譯器aVariable 不是我這個源文件中進(jìn)行聲明的,它來自外部(一個未知的位置)。這樣在單獨編譯該文件gcc -c file2.c 的時候就不會因為缺失聲明式而引發(fā)編譯錯誤了。

有同學(xué)認(rèn)為這里的int aVariable;是聲明,不是定義,這是一種錯誤的觀點。在外部變量中,形如:

,

file1.c file2.c

--------------------------------------------------------------- int aVariable = 3; int aVariable;

int main(){

??

}

其中的int aVariable;定義了外部變量aVariable ,并為之分配了存儲單元。

這同時也成為了外部變量和靜態(tài)變量必須是常量表達(dá)式,且只初始化一次的理由。如果我們對兩邊都進(jìn)行初始化(定義),編譯器將不知道讓誰成為主要初始化的值。事實上,外部變量和靜態(tài)變量的值初始化過程是在編譯時進(jìn)行的,它們的值都被放在靜態(tài)存儲區(qū),也就是我們慣常在匯編中的DATA SEGMENT部分,因此它們必須是常量表達(dá)式,并且有且只有初始化一次,否則我們將可能寫出類似這樣的語句(而這樣的語句本身就是錯誤的): DATA SETMENT

INFO1 "INFOMATION1"

"INFOMATION2" ; 這樣的定義是不允許的

DATA ENDS

??

按照概念extern 通常被看作是外部的,因此通常情況下初始化操作一般是在無extern 的聲明式后的,若在extern 一邊進(jìn)行初始化,則有違常理(主次不分了)。但是由于將初始化步驟僅放在extern 一邊滿足只初始化一次的原則,因此編譯不會出錯,但是根據(jù)不同的編譯器可能會給出警告提示。

參看以下代碼:

包含main 的源文件:

#include

#include

void extern3Processor(void );

int main(void ) {

extern3Processor();

return EXIT_SUCCESS;

}

extern int extern3Variable;

void extern3Processor(void ) {

printf("extern3Processor.extern3Variable:dn",

extern3Variable);

}

externFile.c 文件:(這個文件很簡單,就包含了一個外部變量的定義)

int extern3Variable = 2005;

,

編譯多個文件如下:(將.c 文件編譯為.o 文件,再將這幾個.o 文件一起加載到.exe 文件中(UNIX 中通常為.out 文件),通常在對個別文件作出修改后,我們只需要重新編譯那個文件,然后將這些新舊.o 文件一起加載到.exe 文件中即可。)

gcc -O0 -g3 -Wall -c -fmessage-length=0

-osrc?fectiveArea.o ..src?fectiveArea.c

gcc -O0 -g3 -Wall -c -fmessage-length=0

-osrcexternFile.o ..srcexternFile.c

gcc -oEffectiveArea.exe srcexternFile.o src?fectiveArea.o 輸出結(jié)果:

extern3Processor.extern3Variable:2005

4、之前提到的文字中包含“聲明”和“定義”,它們其實有著嚴(yán)格的區(qū)別。

聲明:變量聲明用于說明變量的屬性(主要是變量的類型)

定義:變量定義除了需要聲明之外,還引起了存儲器分配。

5、在步驟3中我們發(fā)現(xiàn)在任意文件中定義的外部變量均可在其它文件中進(jìn)行使用,只要我們使用了extern 關(guān)鍵字告訴編譯器這個變量的聲明式,我們就可以順利通過編譯。雖然這個方式能夠?qū)崿F(xiàn)在多個文件中共享數(shù)據(jù),但是考慮到文件的管理與項目的不可預(yù)測性,這樣的方式未免讓我們有了些許的擔(dān)心。要是我定義的變量被別人惡意引用了怎么辦?對于只進(jìn)行讀操作的行為,可能這種災(zāi)難是比較小的,但是對于寫操作的行為,就有可能影響到變量的正確性。

用static 聲明限定外部變量和函數(shù),可以將其后聲明的對象的作用域限定為被編譯源文件的剩余部分。

參看以下代碼:

包含main 的源文件:

#include

#include

void static1Processor(void );

int main(void ) {

static1Processor();

return EXIT_SUCCESS;

}

extern int static 1Variable;

void static1Processor(void ) {

printf("static3Processor.static3Variable:dn",

static1Variable);

}

staticFile.c 文件:(這個文件很簡單,就包含了一個外部變量的定義,與externFile.c 所不同的是它的定義增加了static 關(guān)鍵字修飾):

static int static1Variable = 2006;

,

輸出結(jié)果(編譯錯誤,無任何輸出結(jié)果):

由于static int static1Variable = 2006;導(dǎo)致了static1Variable 變量只對staticFile.c 文件可見。

對于函數(shù),它也是具有類似的限制:

包含main 的源文件:

#include

#include

/*兩種定義均無法引用void static2Processor(void);方法的具體實現(xiàn)。*/ /*void static2Processor(void);*/

extern void static2Processor(void );

int main(void ) {

static2Processor();

return EXIT_SUCCESS;

}

staticFile.c :

#include

static int static2Variable = 2007;

static void static2Processor(void ) {

printf("static2Processor.static1Variable:dn",

static2Variable);

}

static 不僅可以用于聲明外部變量,它還可以用于聲明內(nèi)部變量。static 類型的內(nèi)部變量同自動變量一樣,是某個特定局部變量,只能在該函數(shù)中使用,但它與自動變量不同的是,不管其所在函數(shù)是否被調(diào)用,它將一直存在,而不像自動變量那樣,隨著所在函數(shù)的被調(diào)用和退出而存在和消失。換句話說,static 類型的內(nèi)部變量只是一種只能在某個特定函數(shù)中使用但一直占據(jù)存儲空間的變量。

6、因為extern 是為了防止重復(fù)定義,而不是防止重復(fù)聲明。因此對于不可能產(chǎn)生重復(fù)定義的函數(shù)聲明式來說,形如void extern4Processor(void ); 這樣的語句可以不用增加extern ,因為它是重復(fù)的聲明,而不是定義。

因為函數(shù)聲明式本身是不允許嵌套的,因此它天生就是外部的,所以默認(rèn)情況下類似void FunctionName(){……};的形式都有個默認(rèn)的修飾符extern void

FunctionName(){……};只有標(biāo)識了static 的函數(shù)不是外部函數(shù)。

包含main 的源文件:

#include

#include

/*double kinds of declare

* The storage-class specifier, if any,in the declaration specifiers * shall be either extern or static .

*/

,

/*extern void extern4Processor(void);*/

void extern4Processor(void );

int main(void ) {

extern4Processor();

return EXIT_SUCCESS;

}

externFile.c :

#include

int extern4Variable = 2008;

void extern4Processor(void ) {

printf("extern4Processor.extern4Variable:dn",

extern 4Variable);

}

輸出結(jié)果:

extern4Processor.extern4Variable:2008

7、重復(fù)聲明并不可怕,可怕的是重復(fù)定義。

參看以下代碼:

包含main 的源文件:

#include

#include

char repeatVariableWithoutDefinition1; /*declear thrice no hurt*/ char repeatVariableWithoutDefinition1; /*declear thrice no hurt*/ char repeatVariableWithoutDefinition1; /*declear thrice no hurt*/ void repeatVariableWithoutDefinition1Func(void );

int main(void ) {

repeatVariableWithoutDefinition1Func();

return EXIT_SUCCESS;

}

void repeatVariableWithoutDefinition1Func(void ) {

repeatVariableWithoutDefinition1 = 'v';

printf("repeatVariableWithoutDefinition1:cn",

repeatVariableWithoutDefinition1);

}

otherFile.c :

char repeatVariableWithoutDefinition1;

char repeatVariableWithoutDefinition1;

它的無害是因為它們都是在編譯時進(jìn)行分配的,它們并沒有并存,只是僅存了一個罷了。

,

8、至此,上面已經(jīng)生成了許多的聲明/定義。可以看出,我們的函數(shù)是可以跨文件調(diào)用的,而且每次調(diào)用都要寫函數(shù)聲明式。為此,C 語言支持“頭文件”,也就是我們經(jīng)常看到的#include "xxxxx.h"或#include 。其中include <>的時候,將根據(jù)相應(yīng)規(guī)則查找該文件(通常在編譯器所在Includes 文件夾內(nèi)找),但是"" 的時候總是先在源文件(*.c)所在文件夾查找,若找不到則使用與#include <>相同規(guī)則進(jìn)行查找。

#include是一個C 預(yù)處理器,它所指定的文件將在編譯時,將其中內(nèi)容原封不動地替換到#include語句所在的位置。這樣的話,我們就有能力實現(xiàn)了一個地方定義函數(shù),多個地方調(diào)用的功能了。(每次重新寫聲明式難免會造成:1、手誤,導(dǎo)致拼寫錯誤;2、修改維護(hù)困難,可能會漏掉,但又機(jī)緣巧合不會出錯。)

#include頭文件中可以推薦包含文件聲明、宏替換等(事實上可以包含任何的文本)。 因為可以包含任何的文本,所以我們有可能因為重復(fù)定義而導(dǎo)致一些不必要的麻煩,因為畢竟重復(fù)定義是沒有任何意義的,還增加編譯時間。因此在頭文件的內(nèi)部,我們通常采用條件包含來避免重復(fù)地包含。

參看以下代碼:

#ifndef EFFECTIVEAREA_H_

#define EFFECTIVEAREA_H_

/*define the content of EffectiveArea.h here!*/

#endif /* EFFECTIVEAREA_H_ */

注意,宏名字是全局有效的,因此我們必須保證它的唯一性,否則,在判斷的時候,就會因為兩個頭文件之間的互相排斥(被認(rèn)為是同一個文件),但事實上它們之間只是錯誤地定義了名字。為此我們可以用文件名的等價轉(zhuǎn)換來包含它們,因為文件名是唯一的。(文件名包含它的路徑,通常我們將頭文件放入同一個文件夾下,因此我們可以保證在同級文件夾下的文件名的唯一性。)

這樣我們就可以隨心所欲地包含頭文件了,而不必?fù)?dān)心重復(fù)包含頭文件所帶來的壞處了。

9、對于函數(shù)簽名聲明返回值類型為int 的可以省略(不推薦(引發(fā)警告))。

參看以下代碼:

#include

#include

/*We can omit the declaration of function here only when it's returnType is int.

* It only cause compile warning "implicit declaration of function 'nodeclare1Func'"

* Because the default function returnType is 'int'. */

/*But we suggest you explicit declare your function here.*/

/*int nodeclare1Func(int param1); */

/*We can not omit anything here!*/

char nodeclare2Func(void );

int main(void ) {

nodeclare1Func(2009);

標(biāo)簽: