C/C++ 嵌入式筆試題

發(fā)布時(shí)間:2009-4-7 14:53    發(fā)布者:虞美人
關(guān)鍵詞: 筆試 , 嵌入式
預處理器(Preprocessor)

1. 用預處理指令#define 聲明一個(gè)常數,用以表明1年中有多少秒(忽略閏年問(wèn)題)

#define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL
我在這想看到幾件事情:
1). #define 語(yǔ)法的基本知識(例如:不能以分號結束,括號的使用,等等)
2). 懂得預處理器將為你計算常數表達式的值,因此,直接寫(xiě)出你是如何計算一年中有多少秒而不是計算出實(shí)際的值,是更清晰而沒(méi)有代價(jià)的。
3). 意識到這個(gè)表達式將使一個(gè)16位機的整型數溢出-因此要用到長(cháng)整型符號L,告訴編譯器這個(gè)常數是的長(cháng)整型數。
4). 如果你在你的表達式中用到UL(表示無(wú)符號長(cháng)整型),那么你有了一個(gè)好的起點(diǎn)。記住,第一印象很重要。


2. 寫(xiě)一個(gè)“標準”宏MIN,這個(gè)宏輸入兩個(gè)參數并返回較小的一個(gè)。


#define MIN(A,B) ((A) <= (B) (A) : (B))
這個(gè)測試是為下面的目的而設的:
1). 標識#define在宏中應用的基本知識。這是很重要的,因為直到嵌入(inline)操作符變?yōu)闃藴蔆的一部分,宏是方便產(chǎn)生嵌入代碼的唯一方法,對于嵌入式系統來(lái)說(shuō),為了能達到要求的性能,嵌入代碼經(jīng)常是必須的方法。
2). 三重條件操作符的知識。這個(gè)操作符存在C語(yǔ)言中的原因是它使得編譯器能產(chǎn)生比if-then-else更優(yōu)化的代碼,了解這個(gè)用法是很重要的。
3). 懂得在宏中小心地把參數用括號括起來(lái)
4). 我也用這個(gè)問(wèn)題開(kāi)始討論宏的副作用,例如:當你寫(xiě)下面的代碼時(shí)會(huì )發(fā)生什么事?
least = MIN(*p++, b);
其實(shí)宏在編程中的副作用主要表現在編譯器的處理計算上,如果考慮不周全很容易出現重復計算的問(wèn)題。所以寫(xiě)程序要用宏的簡(jiǎn)潔,又要注意其中的陷阱,以防出現莫名其妙的錯誤

3. 預處理器標識#error的目的是什么?

如果你不知道答案,請看參考文獻1。這問(wèn)題對區分一個(gè)正常的伙計和一個(gè)書(shū)呆子是很有用的。只有書(shū)呆子才會(huì )讀C語(yǔ)言課本的附錄去找出象這種
問(wèn)題的答案。當然如果你不是在找一個(gè)書(shū)呆子,那么應試者最好希望自己不要知道答案。


死循環(huán)(Infinite loops)


4. 嵌入式系統中經(jīng)常要用到無(wú)限循環(huán),你怎么樣用C編寫(xiě)死循環(huán)呢?

這個(gè)問(wèn)題用幾個(gè)解決方案。我首選的方案是:
while(1) { }
一些程序員更喜歡如下方案:
for(;;) { }
這個(gè)實(shí)現方式讓我為難,因為這個(gè)語(yǔ)法沒(méi)有確切表達到底怎么回事。如果一個(gè)應試者給出這個(gè)作為方案,我將用這個(gè)作為一個(gè)機會(huì )去探究他們這樣做的
基本原理。如果他們的基本答案是:“我被教著(zhù)這樣做,但從沒(méi)有想到過(guò)為什么!边@會(huì )給我留下一個(gè)壞印象。
第三個(gè)方案是用 goto
Loop:
...
goto Loop;
應試者如給出上面的方案,這說(shuō)明或者他是一個(gè)匯編語(yǔ)言程序員(這也許是好事)或者他是一個(gè)想進(jìn)入新領(lǐng)域的BASIC/FORTRAN程序員。

數據聲明(Data declarations)

5. 用變量a給出下面的定義

a) 一個(gè)整型數(An integer)
b) 一個(gè)指向整型數的指針(A pointer to an integer)
c) 一個(gè)指向指針的的指針,它指向的指針是指向一個(gè)整型數(A pointer to a pointer to an integer)
d) 一個(gè)有10個(gè)整型數的數組(An array of 10 integers)
e) 一個(gè)有10個(gè)指針的數組,該指針是指向一個(gè)整型數的(An array of 10 pointers to integers)
f) 一個(gè)指向有10個(gè)整型數數組的指針(A pointer to an array of 10 integers)
g) 一個(gè)指向函數的指針,該函數有一個(gè)整型參數并返回一個(gè)整型數(A pointer to a function that takes an integer as an argument and returns an integer)
h) 一個(gè)有10個(gè)指針的數組,該指針指向一個(gè)函數,該函數有一個(gè)整型參數并返回一個(gè)整型數( An array of ten pointers to functions that take an integer argument and return an integer )

答案是:
a) int a; // An integer
b) int *a; // A pointer to an integer
c) int **a; // A pointer to a pointer to an integer
d) int a[10]; // An array of 10 integers
e) int *a[10]; // An array of 10 pointers to integers
f) int (*a)[10]; // A pointer to an array of 10 integers
g) int (*a)(int); // A pointer to a function a that takes an integer argument and returns an integer
h) int (*a[10])(int); // An array of 10 pointers to functions that take an integer argument and return an integer


人們經(jīng)常聲稱(chēng)這里有幾個(gè)問(wèn)題是那種要翻一下書(shū)才能回答的問(wèn)題,我同意這種說(shuō)法。當我寫(xiě)這篇文章時(shí),為了確定語(yǔ)法的正確性,我的確查了一下書(shū)。
但是當我被面試的時(shí)候,我期望被問(wèn)到這個(gè)問(wèn)題(或者相近的問(wèn)題)。因為在被面試的這段時(shí)間里,我確定我知道這個(gè)問(wèn)題的答案。應試者如果不知道
所有的答案(或至少大部分答案),那么也就沒(méi)有為這次面試做準備,如果該面試者沒(méi)有為這次面試做準備,那么他又能為什么出準備呢?


Static

6. 關(guān)鍵字static的作用是什么?

這個(gè)簡(jiǎn)單的問(wèn)題很少有人能回答完全。在C語(yǔ)言中,關(guān)鍵字static有三個(gè)明顯的作用:
1). 在函數體,一個(gè)被聲明為靜態(tài)的變量在這一函數被調用過(guò)程中維持其值不變。
2). 在模塊內(但在函數體外),一個(gè)被聲明為靜態(tài)的變量可以被模塊內所用函數訪(fǎng)問(wèn),但不能被模塊外其它函數訪(fǎng)問(wèn)。它是一個(gè)本地的全局變量。
3). 在模塊內,一個(gè)被聲明為靜態(tài)的函數只可被這一模塊內的其它函數調用。那就是,這個(gè)函數被限制在聲明它的模塊的本地范圍內使用。
大多數應試者能正確回答第一部分,一部分能正確回答第二部分,同是很少的人能懂得第三部分。這是一個(gè)應試者的嚴重的缺點(diǎn),因為他顯然不懂得本地化數據和代碼范圍的好處和重要性。


Const

7.關(guān)鍵字const是什么含意?
我只要一聽(tīng)到被面試者說(shuō):“const意味著(zhù)常數”,我就知道我正在和一個(gè)業(yè)余者打交道。去年Dan Saks已經(jīng)在他的文章里完全概括了const的所有用法,因此ESP(譯者:Embedded Systems Programming)的每一位讀者應該非常熟悉const能做什么和不能做什么.如果你從沒(méi)有讀到那篇文章,只要能說(shuō)出const意味著(zhù)“只讀”就可以了。盡管這個(gè)答案不是完全的答案,但我接受它作為一個(gè)正確的答案。(如果你想知道更詳細的答案,仔細讀一下Saks的文章吧。)如果應試者能正確回答這個(gè)問(wèn)題,我將問(wèn)他一個(gè)附加的問(wèn)題:下面的聲明都是什么意思?

const int a;
int const a;
const int *a;
int * const a;
int const * a const;

前兩個(gè)的作用是一樣,a是一個(gè)常整型數。第三個(gè)意味著(zhù)a是一個(gè)指向常整型數的指針(也就是,整型數是不可修改的,但指針可以)。第四個(gè)意思a是一個(gè)指向整型數的常指針(也就是說(shuō),指針指向的整型數是可以修改的,但指針是不可修改的)。最后一個(gè)意味著(zhù)a是一個(gè)指向常整型數的常指針(也就是說(shuō),指針指向的整型數是不可修改的,同時(shí)指針也是不可修改的)。如果應試者能正確回答這些問(wèn)題,那么他就給我留下了一個(gè)好印象。順帶提一句,也許你可能會(huì )問(wèn),即使不用關(guān)鍵字const,也還是能很容易寫(xiě)出功能正確的程序,那么我為什么還要如此看重關(guān)鍵字const呢?我也如下的幾下理由:
1). 關(guān)鍵字const的作用是為給讀你代碼的人傳達非常有用的信息,實(shí)際上,聲明一個(gè)參數為常量是為了告訴了用戶(hù)這個(gè)參數的應用目的。如果你曾花很多時(shí)間清理其它人留下的垃圾,你就會(huì )很快學(xué)會(huì )感謝這點(diǎn)多余的信息。(當然,懂得用const的程序員很少會(huì )留下的垃圾讓別人來(lái)清理的。)
2). 通過(guò)給優(yōu)化器一些附加的信息,使用關(guān)鍵字const也許能產(chǎn)生更緊湊的代碼。
3). 合理地使用關(guān)鍵字const可以使編譯器很自然地保護那些不希望被改變的參數,防止其被無(wú)意的代碼修改。簡(jiǎn)而言之,這樣可以減少bug的出現。

Volatile

8. 關(guān)鍵字volatile有什么含意 并給出三個(gè)不同的例子。

一個(gè)定義為volatile的變量是說(shuō)這變量可能會(huì )被意想不到地改變,這樣,編譯器就不會(huì )去假設這個(gè)變量的值了。精確地說(shuō)就是,優(yōu)化器在用到這個(gè)變量時(shí)必須每次都小心地重新讀取這個(gè)變量的值,而不是使用保存在寄存器里的備份。下面是volatile變量的幾個(gè)例子:
1). 并行設備的硬件寄存器(如:狀態(tài)寄存器)
2). 一個(gè)中斷服務(wù)子程序中會(huì )訪(fǎng)問(wèn)到的非自動(dòng)變量(Non-automatic variables)
3). 多線(xiàn)程應用中被幾個(gè)任務(wù)共享的變量
回答不出這個(gè)問(wèn)題的人是不會(huì )被雇傭的。我認為這是區分C程序員和嵌入式系統程序員的最基本的問(wèn)題。嵌入式系統程序員經(jīng)常同硬件、中斷、RTOS等等打交道,所用這些都要求volatile變量。不懂得volatile內容將會(huì )帶來(lái)災難。
假設被面試者正確地回答了這是問(wèn)題(嗯,懷疑這否會(huì )是這樣),我將稍微深究一下,看一下這家伙是不是直正懂得volatile完全的重要性。
1). 一個(gè)參數既可以是const還可以是volatile嗎?解釋為什么。
2). 一個(gè)指針可以是volatile 嗎?解釋為什么。
3). 下面的函數有什么錯誤:
int square(volatile int *ptr)
{
return *ptr * *ptr;
}
下面是答案:
1). 是的。一個(gè)例子是只讀的狀態(tài)寄存器。它是volatile因為它可能被意想不到地改變。它是const因為程序不應該試圖去修改它。
2). 是的。盡管這并不很常見(jiàn)。一個(gè)例子是當一個(gè)中服務(wù)子程序修該一個(gè)指向一個(gè)buffer的指針時(shí)。
3). 這段代碼的有個(gè)惡作劇。這段代碼的目的是用來(lái)返指針*ptr指向值的平方,但是,由于*ptr指向一個(gè)volatile型參數,編譯器將產(chǎn)生類(lèi)似下面的代碼:
int square(volatile int *ptr)
{
int a,b;
a = *ptr;
b = *ptr;
return a * b;
}
由于*ptr的值可能被意想不到地該變,因此a和b可能是不同的。結果,這段代碼可能返不是你所期望的平方值!正確的代碼如下:
long square(volatile int *ptr)
{
int a;
a = *ptr;
return a * a;
}

位操作(Bit manipulation)

9. 嵌入式系統總是要用戶(hù)對變量或寄存器進(jìn)行位操作。給定一個(gè)整型變量a,寫(xiě)兩段代碼,第一個(gè)設置a的bit 3,第二個(gè)清除a 的bit 3。在以上兩個(gè)操作中,要保持其它位不變。

對這個(gè)問(wèn)題有三種基本的反應
1). 不知道如何下手。該被面者從沒(méi)做過(guò)任何嵌入式系統的工作。
2). 用bit fields。Bit fields是被扔到C語(yǔ)言死角的東西,它保證你的代碼在不同編譯器之間是不可移植的,同時(shí)也保證了的你的代碼是不可重用的。我最近不幸看到 Infineon為其較復雜的通信芯片寫(xiě)的驅動(dòng)程序,它用到了bit fields因此完全對我無(wú)用,因為我的編譯器用其它的方式來(lái)實(shí)現bit fields的。從道德講:永遠不要讓一個(gè)非嵌入式的家伙粘實(shí)際硬件的邊。
3). 用 #defines 和 bit masks 操作。這是一個(gè)有極高可移植性的方法,是應該被用到的方法。最佳的解決方案如下:
#define BIT3 (0x1<<3)
static int a;
void set_bit3(void)
{
a |= BIT3;
}
void clear_bit3(void)
{
a &= ~BIT3;
}
一些人喜歡為設置和清除值而定義一個(gè)掩碼同時(shí)定義一些說(shuō)明常數,這也是可以接受的。我希望看到幾個(gè)要點(diǎn):說(shuō)明常數、|=和&=~操作。

訪(fǎng)問(wèn)固定的內存位置(Accessing fixed memory locations)

10. 嵌入式系統經(jīng)常具有要求程序員去訪(fǎng)問(wèn)某特定的內存位置的特點(diǎn)。在某工程中,要求設置一絕對地址為0x67a9的整型變量的值為0xaa66。編譯器是一個(gè)純粹的ANSI編譯器。寫(xiě)代碼去完成這一任務(wù)。

這一問(wèn)題測試你是否知道為了訪(fǎng)問(wèn)一絕對地址把一個(gè)整型數強制轉換(typecast)為一指針是合法的。這一問(wèn)題的實(shí)現方式隨著(zhù)個(gè)人風(fēng)格不同而不同。典型的類(lèi)似代碼如下:
int *ptr;
ptr = (int *)0x67a9;
*ptr = 0xaa55;

一個(gè)較晦澀的方法是:
*(int * const)(0x67a9) = 0xaa55;

即使你的品味更接近第二種方案,但我建議你在面試時(shí)使用第一種方案。

中斷(Interrupts)

11. 中斷是嵌入式系統中重要的組成部分,這導致了很多編譯開(kāi)發(fā)商提供一種擴展—讓標準C支持中斷。具代表事實(shí)是,產(chǎn)生了一個(gè)新的關(guān)鍵字 __interrupt。下面的代碼就使用了__interrupt關(guān)鍵字去定義了一個(gè)中斷服務(wù)子程序(ISR),請評論一下這段代碼的。

__interrupt double compute_area (double radius)
{
     double area = PI * radius * radius;
     printf(" Area = %f", area);
     return area;
}

這個(gè)函數有太多的錯誤了,以至讓人不知從何說(shuō)起了:
1). ISR 不能返回一個(gè)值。如果你不懂這個(gè),那么你不會(huì )被雇用的。
2). ISR 不能傳遞參數。如果你沒(méi)有看到這一點(diǎn),你被雇用的機會(huì )等同第一項。
3). 在許多的處理器/編譯器中,浮點(diǎn)一般都是不可重入的。有些處理器/編譯器需要讓額處的寄存器入棧,有些處理器/編譯器就是不允許在ISR中做浮點(diǎn)運算。此外,ISR應該是短而有效率的,在ISR中做浮點(diǎn)運算是不明智的。
4). 與第三點(diǎn)一脈相承,printf()經(jīng)常有重入和性能上的問(wèn)題。如果你丟掉了第三和第四點(diǎn),我不會(huì )太為難你的。不用說(shuō),如果你能得到后兩點(diǎn),那么你的被雇用前景越來(lái)越光明了。

代碼例子(Code examples)

12 . 下面的代碼輸出是什么,為什么?

void foo(void)
{
     unsigned int a = 6;
     int b = -20;
     (a+b > 6) puts("> 6") : puts("<= 6");
}

這個(gè)問(wèn)題測試你是否懂得C語(yǔ)言中的整數自動(dòng)轉換原則,我發(fā)現有些開(kāi)發(fā)者懂得極少這些東西。不管如何,這無(wú)符號整型問(wèn)題的答案是輸出是 “>6”。原因是當表達式中存在有符號類(lèi)型和無(wú)符號類(lèi)型時(shí)所有的操作數都自動(dòng)轉換為無(wú)符號類(lèi)型。因此-20變成了一個(gè)非常大的正整數,所以該表達式計算出的結果大于6。這一點(diǎn)對于應當頻繁用到無(wú)符號數據類(lèi)型的嵌入式系統來(lái)說(shuō)是豐常重要的。如果你答錯了這個(gè)問(wèn)題,你也就到了得不到這份工作的邊緣。

13. 評價(jià)下面的代碼片斷:

unsigned int zero = 0;
unsigned int compzero = 0xFFFF;
/*1's complement of zero */

對于一個(gè)int型不是16位的處理器為說(shuō),上面的代碼是不正確的。應編寫(xiě)如下:

unsigned int compzero = ~0;

這一問(wèn)題真正能揭露出應試者是否懂得處理器字長(cháng)的重要性。在我的經(jīng)驗里,好的嵌入式程序員非常準確地明白硬件的細節和它的局限,然而PC機程序往往把硬件作為一個(gè)無(wú)法避免的煩惱。
到了這個(gè)階段,應試者或者完全垂頭喪氣了或者信心滿(mǎn)滿(mǎn)志在必得。如果顯然應試者不是很好,那么這個(gè)測試就在這里結束了。但如果顯然應試者做得不錯,那么我就扔出下面的追加問(wèn)題,這些問(wèn)題是比較難的,我想僅僅非常優(yōu)秀的應試者能做得不錯。提出這些問(wèn)題,我希望更多看到應試者應付問(wèn)題的方法,而不是答案。不管如何,你就當是這個(gè)娛樂(lè )吧…

動(dòng)態(tài)內存分配(Dynamic memory allocation)

14. 盡管不像非嵌入式計算機那么常見(jiàn),嵌入式系統還是有從堆(heap)中動(dòng)態(tài)分配內存的過(guò)程的。那么嵌入式系統中,動(dòng)態(tài)分配內存可能發(fā)生的問(wèn)題是什么?

這里,我期望應試者能提到內存碎片,碎片收集的問(wèn)題,變量的持行時(shí)間等等。這個(gè)主題已經(jīng)在ESP雜志中被廣泛地討論過(guò)了(主要是 P.J. Plauger, 他的解釋遠遠超過(guò)我這里能提到的任何解釋?zhuān),所有回過(guò)頭看一下這些雜志吧!讓?xiě)囌哌M(jìn)入一種虛假的安全感覺(jué)后,我拿出這么一個(gè)小節目:下面的代碼片段的輸出是什么,為什么?

char *ptr;
if ((ptr = (char *)malloc(0)) == NULL)
puts("Got a null pointer");
else
puts("Got a valid pointer");

這是一個(gè)有趣的問(wèn)題。最近在我的一個(gè)同事不經(jīng)意把0值傳給了函數malloc,得到了一個(gè)合法的指針之后,我才想到這個(gè)問(wèn)題。這就是上面的代碼,該代碼的輸出是“Got a valid pointer”。我用這個(gè)來(lái)開(kāi)始討論這樣的一問(wèn)題,看看被面試者是否想到庫例程這樣做是正確。得到正確的答案固然重要,但解決問(wèn)題的方法和你做決定的基本原理更重要些。

Typedef

15. Typedef 在C語(yǔ)言中頻繁用以聲明一個(gè)已經(jīng)存在的數據類(lèi)型的同義字。也可以用預處理器做類(lèi)似的事。例如,思考一下下面的例子:
#define dPS struct s *
typedef struct s * tPS;

以上兩種情況的意圖都是要定義dPS 和 tPS 作為一個(gè)指向結構s指針。哪種方法更好呢?(如果有的話(huà))為什么?
這是一個(gè)非常微妙的問(wèn)題,任何人答對這個(gè)問(wèn)題(正當的原因)是應當被恭喜的。答案是:typedef更好。思考下面的例子:
dPS p1,p2;
tPS p3,p4;

第一個(gè)擴展為
struct s * p1, p2;

上面的代碼定義p1為一個(gè)指向結構的指,p2為一個(gè)實(shí)際的結構,這也許不是你想要的。第二個(gè)例子正確地定義了p3 和p4 兩個(gè)指針。


16. C語(yǔ)言同意一些令人震驚的結構,下面的結構是合法的嗎,如果是它做些什么?
int a = 5, b = 7, c;
c = a+++b;

這個(gè)問(wèn)題將做為這個(gè)測驗的一個(gè)愉快的結尾。不管你相不相信,上面的例子是完全合乎語(yǔ)法的。問(wèn)題是編譯器如何處理它?水平不高的編譯作者實(shí)際上會(huì )爭論這個(gè)問(wèn)題,根據最處理原則,編譯器應當能處理盡可能所有合法的用法。因此,上面的代碼被處理成:
c = a++ + b;
因此, 這段代碼持行后a = 6, b = 7, c = 12。


1、請定義一個(gè)宏,比較兩個(gè)數a、b的大小,不能使用大于、小于、if語(yǔ)句

#define Max(a,b) ( a/b)?a:b

2、如何輸出源文件的標題和目前執行行的行數

int line = __LINE__;

char *file = __FILE__;

cout<<"file name is "<<(file)<<",line is "<

3、兩個(gè)數相乘,小數點(diǎn)后位數沒(méi)有限制,請寫(xiě)一個(gè)高精度算法

4、寫(xiě)一個(gè)病毒

while (1)

{

int *p = new int[10000000];

}

5、不使用額外空間,將 A,B兩鏈表的元素交*歸并

6、將樹(shù)序列化 轉存在數組或 鏈表中

struct st{

int i;

short s;

char c;

};

sizeof(struct st);

7、

char * p1;

void * p2;

int p3;

char p4[10];

sizeof(p1...p4) =?

8、

4,4,4,10

二分查找

快速排序

雙向鏈表的刪除結點(diǎn)
 
1。主鍵用于唯一標識表中的行數據,一個(gè)主鍵值對應一行數據。另外,會(huì )自動(dòng)在主鍵上創(chuàng )建索引,用于加快查詢(xún)。
2。外鍵用于兩個(gè)表的聯(lián)系。兩個(gè)表必須具有相同類(lèi)型的屬性,在該屬性上有相同的值。該屬性應為其中一個(gè)表的主鍵,在另外一個(gè)表設置為外鍵。

主鍵:唯一標識,不能為空,加快查詢(xún)速度,自動(dòng)創(chuàng )建索引,
外鍵:約束內表的數據的更新,從定義外鍵時(shí)可以發(fā)現 外鍵是和主鍵表聯(lián)系,數據類(lèi)型要統一,長(cháng)度(存儲大小)要統一。這樣在更新數據的時(shí)候會(huì )保持一致性。
索引能將數據按一定的規則進(jìn)行排列這樣進(jìn)行查詢(xún)時(shí)能很快定位數據,從而加快查詢(xún)的速度,
但不合適的索引將導致INSERT或UPDATE很慢


#include<stdio.h>
#include<stdlib.h>

int   main(void)
{
       union A{
         char a;
         char y:3;
         char z:3;
         char x:2;
       }a;

       a.a = 0x67;
       printf("a.a =%0x a.x=%0x \t a.y=%0x\t a.z=%0x\n",a.a, a.x, a.y, a.z );
       return 0;
}
結果
a.a =67 a.x=ffffffff     a.y=ffffffff a.z=ffffffff
a.a =64 a.x=0 a.y=fffffffc a.z=fffffffc
a.a =65 a.x=1 a.y=fffffffd a.z=fffffffd

很久沒(méi)動(dòng)c語(yǔ)言了,很多基礎性的東西都沒(méi)有深入學(xué)習。今天看到關(guān)于聯(lián)合體位域面試題,想了半天才知道程序答案的來(lái)由~~汗顏~~
如果單從位域來(lái)理解這個(gè)還是簡(jiǎn)單,問(wèn)題的關(guān)鍵是理解其在計算機內的存取規則。
對a.a=64, 單從取位(二進(jìn)制)上可知a.x=00, a.y=101, a.z=101.目前通用計算機x86大都是32位機,我的機器也是32位,在存取上默認是存取32位。對每個(gè)數而言第一位是符號位,補碼存儲。那么可以理解a.x的補碼就是00000000, a.y的補碼就是11111100, a.z的補碼就是11111100.這樣看比較自然,但如果輸出結果是10進(jìn)制,就會(huì )覺(jué)得難以理解。當然關(guān)鍵還是對數據的存取規則和編碼的熟悉。
a.a=0x64的10進(jìn)制結果是a.x=0, a.y=-4 ,a.z=-4
補充一點(diǎn),union內的變量順序對結果不影響(每次只可能有一種解釋是合理的,這個(gè)跟struct顯然不同)

關(guān)于位域在結構體的應用主要要注意內存對齊規則的理解和空域的理解
http://blog.csdn.net/jiyucn/archive/2006/07/01/862085.aspx
使用位域的主要目的是壓縮存儲,其大致規則為:
1)   如果相鄰位域字段的類(lèi)型相同,且其位寬之和小于類(lèi)型的sizeof大小,則后面的字段將緊鄰前一個(gè)字段存儲,直到不能容納為止;
2)   如果相鄰位域字段的類(lèi)型相同,但其位寬之和大于類(lèi)型的sizeof大小,則后面的字段將從新的存儲單元開(kāi)始,其偏移量為其類(lèi)型大小的整數倍;
3)   如果相鄰的位域字段的類(lèi)型不同,則各編譯器的具體實(shí)現有差異,VC6采取不壓縮方式,Dev-C++采取壓縮方式;
4)   如果位域字段之間穿插著(zhù)非位域字段,則不進(jìn)行壓縮;
5)   整個(gè)結構體的總大小為最寬基本類(lèi)型成員大小的整數倍。

#include <stdio.h>
int main()
{
union
{
            struct
            {
                     unsigned short s1:3;
                     unsigned short s2:3;
                     unsigned short s3:3;
            }x;
            char c;
}v;
v.c=100;

printf("%d\n",sizeof(v));
printf("s1=%d\n",v.x.s1);
printf("s2=%d\n",v.x.s2);
printf("s3=%d\n",v.x.s3);
return 0;
}
fc6--linux下gcc-4.1.1
2
s1=4
s2=4
s3=5
windows xp2下vc6.0
2
s1=4
s2=4
s3=1

可見(jiàn)s3的結果并不一樣vc6.0的結果如果只是按位取,就很好理解,這樣跟之前的union的存取規則又不一樣了~~而對于gcc-4.1.1,s3=5還沒(méi)想出該結果的原因。同時(shí)考慮
struct
            {
                     unsigned short s1:3;
                     unsigned short s2:3;
                     unsigned short s3:3;
    unsigned short s4:7;
            }x;
   最后s4的結果更加撲朔迷離~~請大家多指點(diǎn)~·
#include<stdio.h>
#include<stdlib.h>

int   main(void)
{
       union A{
         char a;
         char y:3;
         char z:3;
         char x:2;
       }a;

       a.a = 0x67;
       printf("a.a =%0x a.x=%0x \t a.y=%0x\t a.z=%0x\n",a.a, a.x, a.y, a.z );
       return 0;
}
結果
a.a =67 a.x=ffffffff     a.y=ffffffff a.z=ffffffff
a.a =64 a.x=0 a.y=fffffffc a.z=fffffffc
a.a =65 a.x=1 a.y=fffffffd a.z=fffffffd

很久沒(méi)動(dòng)c語(yǔ)言了,很多基礎性的東西都沒(méi)有深入學(xué)習。今天看到關(guān)于聯(lián)合體位域面試題,想了半天才知道程序答案的來(lái)由~~汗顏~~
如果單從位域來(lái)理解這個(gè)還是簡(jiǎn)單,問(wèn)題的關(guān)鍵是理解其在計算機內的存取規則。
對a.a=64, 單從取位(二進(jìn)制)上可知a.x=00, a.y=101, a.z=101.目前通用計算機x86大都是32位機,我的機器也是32位,在存取上默認是存取32位。對每個(gè)數而言第一位是符號位,補碼存儲。那么可以理解a.x的補碼就是00000000, a.y的補碼就是11111100, a.z的補碼就是11111100.這樣看比較自然,但如果輸出結果是10進(jìn)制,就會(huì )覺(jué)得難以理解。當然關(guān)鍵還是對數據的存取規則和編碼的熟悉。
a.a=0x64的10進(jìn)制結果是a.x=0, a.y=-4 ,a.z=-4
補充一點(diǎn),union內的變量順序對結果不影響(每次只可能有一種解釋是合理的,這個(gè)跟struct顯然不同)

關(guān)于位域在結構體的應用主要要注意內存對齊規則的理解和空域的理解
http://blog.csdn.net/jiyucn/archive/2006/07/01/862085.aspx
使用位域的主要目的是壓縮存儲,其大致規則為:
1)   如果相鄰位域字段的類(lèi)型相同,且其位寬之和小于類(lèi)型的sizeof大小,則后面的字段將緊鄰前一個(gè)字段存儲,直到不能容納為止;
2)   如果相鄰位域字段的類(lèi)型相同,但其位寬之和大于類(lèi)型的sizeof大小,則后面的字段將從新的存儲單元開(kāi)始,其偏移量為其類(lèi)型大小的整數倍;
3)   如果相鄰的位域字段的類(lèi)型不同,則各編譯器的具體實(shí)現有差異,VC6采取不壓縮方式,Dev-C++采取壓縮方式;
4)   如果位域字段之間穿插著(zhù)非位域字段,則不進(jìn)行壓縮;
5)   整個(gè)結構體的總大小為最寬基本類(lèi)型成員大小的整數倍。

#include <stdio.h>
int main()
{
union
{
            struct
            {
                     unsigned short s1:3;
                     unsigned short s2:3;
                     unsigned short s3:3;
            }x;
            char c;
}v;
v.c=100;

printf("%d\n",sizeof(v));
printf("s1=%d\n",v.x.s1);
printf("s2=%d\n",v.x.s2);
printf("s3=%d\n",v.x.s3);
return 0;
}
fc6--linux下gcc-4.1.1
2
s1=4
s2=4
s3=5
windows xp2下vc6.0
2
s1=4
s2=4
s3=1

可見(jiàn)s3的結果并不一樣vc6.0的結果如果只是按位取,就很好理解,這樣跟之前的union的存取規則又不一樣了~~而對于gcc-4.1.1,s3=5還沒(méi)想出該結果的原因。同時(shí)考慮
struct
            {
                     unsigned short s1:3;
                     unsigned short s2:3;
                     unsigned short s3:3;
    unsigned short s4:7;
            }x;
   最后s4的結果更加撲朔迷離~~請大家多指點(diǎn)~·


C++的static有兩種用法:面向過(guò)程程序設計中的static和面向對象程序設計中的static。前者應用于普通變量和函數,不涉及類(lèi);后者主要說(shuō)明static在類(lèi)中的作用。

一、面向過(guò)程設計中的static

1、靜態(tài)全局變量

在全局變量前,加上關(guān)鍵字static,該變量就被定義成為一個(gè)靜態(tài)全局變量。靜態(tài)全局變量有以下特點(diǎn):
該變量在全局數據區分配內存;
未經(jīng)初始化的靜態(tài)全局變量會(huì )被程序自動(dòng)初始化為0(自動(dòng)變量的值是隨機的,除非它被顯式初始化);
靜態(tài)全局變量在聲明它的整個(gè)文件都是可見(jiàn)的,而在文件之外是不可見(jiàn)的;
靜態(tài)變量都在全局數據區分配內存,包括后面將要提到的靜態(tài)局部變量。對于一個(gè)完整的程序,在內存中的分布情況如下圖:
代碼區
全局數據區
堆區
棧區

一般程序的由new產(chǎn)生的動(dòng)態(tài)數據存放在堆區,函數內部的自動(dòng)變量存放在棧區。自動(dòng)變量一般會(huì )隨著(zhù)函數的退出而釋放空間,靜態(tài)數據(即使是函數內部的靜 態(tài)局部變量)也存放在全局數據區。全局數據區的數據并不會(huì )因為函數的退出而釋放空間。

的確,定義全局變量就可以實(shí)現變量在文件中的共享,但定義靜態(tài)全局變量還有以下好處:
靜態(tài)全局變量不能被其它文件所用;
其它文件中可以定義相同名字的變量,不會(huì )發(fā)生沖突;

2、靜態(tài)局部變量

在局部變量前,加上關(guān)鍵字static,該變量就被定義成為一個(gè)靜態(tài)局部變量。通常,在函數體內定義了一個(gè)變量,每當程序運行到該語(yǔ)句時(shí)都會(huì )給該局部變量分配棧內存。但隨著(zhù)程序退出函數體,系統就會(huì )收回棧內存,局部變量也相應失效。
但有時(shí)候我們需要在兩次調用之間對變量的值進(jìn)行保存。通常的想法是定義一個(gè)全局變量來(lái)實(shí)現。但這樣一來(lái),變量已經(jīng)不再屬于函數本身了,不再僅受函數的控制,給程序的維護帶來(lái)不便。
靜態(tài)局部變量正好可以解決這個(gè)問(wèn)題。靜態(tài)局部變量保存在全局數據區,而不是保存在棧中,每次的值保持到下一次調用,直到下次賦新值。

example:

void foo()
{
static int a;
a++;
cout<<a<<endl;
}
int main()
{
foo();
foo();
foo();
return 0;
}

結果是 1 2 3 每次foo()退出后,并未銷(xiāo)毀變量a,因為它是存放在全局數據區的,不是?臻g。
靜態(tài)局部變量有以下特點(diǎn):

該變量在全局數據區分配內存;
靜態(tài)局部變量在程序執行到該對象的聲明處時(shí)被首次初始化,即以后的函數調用不再進(jìn)行初始化;
靜態(tài)局部變量一般在聲明處初始化,如果沒(méi)有顯式初始化,會(huì )被程序自動(dòng)初始化為0;
它始終駐留在全局數據區,直到程序運行結束。但其作用域為局部作用域,當定義它的函數或語(yǔ)句塊結束時(shí),其作用域隨之結束;

3、靜態(tài)函數

在函數的返回類(lèi)型前加上static關(guān)鍵字,函數即被定義為靜態(tài)函數。靜態(tài)函數與普通函數不同,它只能在聲明它的文件當中可見(jiàn),不能被其它文件使用。

靜態(tài)函數的例子:

//Example 4

#include <iostream.h>

static void fn();//聲明靜態(tài)函數

void main()

{

fn();

}

void fn()//定義靜態(tài)函數

{

int n=10; cout<<n<<endl;

}
定義靜態(tài)函數的好處:
靜態(tài)函數不能被其它文件所用;
其它文件中可以定義相同名字的函數,不會(huì )發(fā)生沖突;


二、面向對象的static關(guān)鍵字(類(lèi)中的static關(guān)鍵字)

1、靜態(tài)數據成員

在類(lèi)內數據成員的聲明前加上關(guān)鍵字static,該數據成員就是類(lèi)內的靜態(tài)數據成員。先舉一個(gè)靜態(tài)數據成員的例子。

可以看出,靜態(tài)數據成員有以下特點(diǎn):
對于非靜態(tài)數據成員,每個(gè)類(lèi)對象都有自己的拷貝。而靜態(tài)數據成員被當作是類(lèi)的成員。無(wú)論這個(gè)類(lèi)的對象被定義了多少個(gè),靜態(tài)數據成員在程序中也只有一份拷貝,由該類(lèi)型的所有對象共享訪(fǎng)問(wèn)。也就是說(shuō),靜態(tài)數據成員是該類(lèi)的所有對象所共有的。對該類(lèi)的多個(gè)對象來(lái)說(shuō),靜態(tài)數據成員只分配一次內存,供所有對象共用。所以,靜態(tài)數據成員的值對每個(gè)對象都是一樣的,它的值可以更新;
靜態(tài)數據成員存儲在全局數據區。靜態(tài)數據成員定義時(shí)要分配空間,所以不能在類(lèi)聲明中定義。在Example 5中,語(yǔ)句int Myclass::Sum=0;是定義靜態(tài)數據成員;
靜態(tài)數據成員和普通數據成員一樣遵從public,protected,private訪(fǎng)問(wèn)規則;
因為靜態(tài)數據成員在全局數據區分配內存,屬于本類(lèi)的所有對象共享,所以,它不屬于特定的類(lèi)對象,在沒(méi)有產(chǎn)生類(lèi)對象時(shí)其作用域就可見(jiàn),即在沒(méi)有產(chǎn)生類(lèi)的實(shí)例時(shí),我們就可以操作它;
靜態(tài)數據成員初始化與一般數據成員初始化不同。靜態(tài)數據成員初始化的格式為:
<數據類(lèi)型><類(lèi)名>::<靜態(tài)數據成員名>=<值>
類(lèi)的靜態(tài)數據成員有兩種訪(fǎng)問(wèn)形式:
<類(lèi)對象名>.<靜態(tài)數據成員名> 或 <類(lèi)類(lèi)型名>::<靜態(tài)數據成員名>
如果靜態(tài)數據成員的訪(fǎng)問(wèn)權限允許的話(huà)(即public的成員),可在程序中,按上述格式來(lái)引用靜態(tài)數據成員 ;
靜態(tài)數據成員主要用在各個(gè)對象都有相同的某項屬性的時(shí)候。比如對于一個(gè)存款類(lèi),每個(gè)實(shí)例的利息都是相同的。所以,應該把利息設為存款類(lèi)的靜態(tài)數據成員。這有兩個(gè)好處,第一,不管定義多少個(gè)存款類(lèi)對象,利息數據成員都共享分配在全局數據區的內存,所以節省存儲空間。第二,一旦利息需要改變時(shí),只要改變一次,則所有存款類(lèi)對象的利息全改變過(guò)來(lái)了;
同全局變量相比,使用靜態(tài)數據成員有兩個(gè)優(yōu)勢:
靜態(tài)數據成員沒(méi)有進(jìn)入程序的全局名字空間,因此不存在與程序中其它全局名字沖突的可能性;
可以實(shí)現信息隱藏。靜態(tài)數據成員可以是private成員,而全局變量不能;

2、靜態(tài)成員函數
與靜態(tài)數據成員一樣,我們也可以創(chuàng )建一個(gè)靜態(tài)成員函數,它為類(lèi)的全部服務(wù)而不是為某一個(gè)類(lèi)的具體對象服務(wù)。靜態(tài)成員函數與靜態(tài)數據成員一樣,都是類(lèi)的內部 實(shí)現,屬于類(lèi)定義的一部分。普通的成員函數一般都隱含了一個(gè)this指針,this指針指向類(lèi)的對象本身,因為普通成員函數總是具體的屬于某個(gè)類(lèi)的具體對象的。通常情況下,this 是缺省的。如函數fn()實(shí)際上是this->fn()。但是與普通函數相比,靜態(tài)成員函數由于不是與任何的對象相聯(lián)系,因此它不具有this指針。從這個(gè)意義上講,它無(wú)法訪(fǎng)問(wèn)屬于類(lèi)對象的非靜態(tài)數據成員,也無(wú)法訪(fǎng)問(wèn)非靜態(tài)成員函數,它只能調用其余的靜態(tài)成員函數。

關(guān)于靜態(tài)成員函數,可以總結為以下幾點(diǎn):
出現在類(lèi)體外的函數定義不能指定關(guān)鍵字static;
靜態(tài)成員之間可以相互訪(fǎng)問(wèn),包括靜態(tài)成員函數訪(fǎng)問(wèn)靜態(tài)數據成員和訪(fǎng)問(wèn)靜態(tài)成員函數;
非靜態(tài)成員函數可以任意地訪(fǎng)問(wèn)靜態(tài)成員函數和靜態(tài)數據成員;
靜態(tài)成員函數不能訪(fǎng)問(wèn)非靜態(tài)成員函數和非靜態(tài)數據成員;
由于沒(méi)有this指針的額外開(kāi)銷(xiāo),因此靜態(tài)成員函數與類(lèi)的全局函數相比速度上會(huì )有少許的增長(cháng);
調用靜態(tài)成員函數,可以用成員訪(fǎng)問(wèn)操作符(.)和(->)為一個(gè)類(lèi)的對象或指向類(lèi)對象的指針調用靜態(tài)成員函數,也可以直接使用如下格式:
<類(lèi)名>::<靜態(tài)成員函數名>(<參數表>)
調用類(lèi)的靜態(tài)成員函數。

 

堆和棧的區別


一般認為在c中分為這幾個(gè)存儲區
1棧 - 有編譯器自動(dòng)分配釋放
2堆 - 一般由程序員分配釋放,若程序員不釋放,程序結束時(shí)可能由OS回收
3全局區(靜態(tài)區),全局變量和靜態(tài)變量的存儲是放在一塊的,初始化的全局變量和靜
態(tài)變量在一塊區域,未初始化的全局變量和未初始化的靜態(tài)變量在相鄰的另一塊區域。
- 程序結束釋放
4另外還有一個(gè)專(zhuān)門(mén)放常量的地方。 - 程序結束釋放
在函數體中定義的變量通常是在棧上,用malloc, calloc, realloc等分配內存的函數分
配得到的就是在堆上。在所有函數體外定義的是全局量,加了static修飾符后不管在哪
里都存放在全局區(靜態(tài)區),在所有函數體外定義的static變量表示在該文件中有效,
不能extern到別的文件用,在函數體內定義的static表示只在該函數體內有效。另外,
函數中的"adgfdf"這樣的字符串存放在常量區。
比如:
int a = 0; 全局初始化區
char *p1; 全局未初始化區
main()
{
int b; 棧
char s[] = "abc";棧
char *p2; 棧
char *p3 = "123456"; 123456\0在常量區,p3在棧上。
static int c =0; 全局(靜態(tài))初始化區
p1 = (char *)malloc(10);
p2 = (char *)malloc(20);
分配得來(lái)得10和20字節的區域就在堆區。
strcpy(p1, "123456"); 123456\0放在常量區,編譯器可能會(huì )將它與p3所指向的"12345
6"優(yōu)化成一塊。
}
還有就是函數調用時(shí)會(huì )在棧上有一系列的保留現場(chǎng)及傳遞參數的操作。
棧的空間大小有限定,vc的缺省是2M。棧不夠用的情況一般是程序中分配了大量數組和
遞歸函數層次太深。有一點(diǎn)必須知道,當一個(gè)函數調用完返回后它會(huì )釋放該函數中所有
的?臻g。棧是由編譯器自動(dòng)管理的,不用你操心。
堆是動(dòng)態(tài)分配內存的,并且你可以分配使用很大的內存。但是用不好會(huì )產(chǎn)生內存泄漏。
并且頻繁地malloc和free會(huì )產(chǎn)生內存碎片(有點(diǎn)類(lèi)似磁盤(pán)碎片),因為c分配動(dòng)態(tài)內存時(shí)
是尋找匹配的內存的。而用棧則不會(huì )產(chǎn)生碎片。
在棧上存取數據比通過(guò)指針在堆上存取數據快些。
一般大家說(shuō)的堆棧和棧是一樣的,就是棧(stack),而說(shuō)堆時(shí)才是堆heap.
棧是先入后出的,一般是由高地址向低地址生長(cháng)。


堆(heap)和棧(stack)是C/C++編程不可避免會(huì )碰到的兩個(gè)基本概念。首先,這兩個(gè)概念

都可以在講數據結構的書(shū)中找到,他們都是基本的數據結構,雖然棧更為簡(jiǎn)單一些。

在具體的C/C++編程框架中,這兩個(gè)概念并不是并行的。對底層機器代碼的研究可以揭示

,棧是機器系統提供的數據結構,而堆則是C/C++函數庫提供的。

具體地說(shuō),現代計算機(串行執行機制),都直接在代碼底層支持棧的數據結構。這體現

在,有專(zhuān)門(mén)的寄存器指向棧所在的地址,有專(zhuān)門(mén)的機器指令完成數據入棧出棧的操作。

這種機制的特點(diǎn)是效率高,支持的數據有限,一般是整數,指針,浮點(diǎn)數等系統直接支

持的數據類(lèi)型,并不直接支持其他的數據結構。因為棧的這種特點(diǎn),對棧的使用在程序

中是非常頻繁的。對子程序的調用就是直接利用棧完成的。機器的call指令里隱含了把

返回地址推入棧,然后跳轉至子程序地址的操作,而子程序中的ret指令則隱含從堆棧中

彈出返回地址并跳轉之的操作。C/C++中的自動(dòng)變量是直接利用棧的例子,這也就是為什

么當函數返回時(shí),該函數的自動(dòng)變量自動(dòng)失效的原因(因為 顏換指戳說(shuō)饔們暗 狀態(tài))。

 

和棧不同,堆的數據結構并不是由系統(無(wú)論是機器系統還是操作系統)支持的,而是由

函數庫提供的;镜膍alloc/realloc/free函數維護了一套內部的堆數據結構。當程序

使用這些函數去獲得新的內存空間時(shí),這套函數首先試圖從內部堆中尋找可用的內存空

間,如果沒(méi)有可以使用的內存空間,則試圖利用系統調用來(lái)動(dòng)態(tài)增加程序數據段的內存

大小,新分配得到的空間首先被組織進(jìn)內部堆中去,然后再以適當的形式返回給調用者

。當程序釋放分配的內存空間時(shí),這片內存空間被返回內部堆結構中,可能會(huì )被適當的

處理(比如和其他空閑空間合并成更大的空閑空間),以更適合下一次內存分配申請。這

套復雜的分配機制實(shí)際上相當于一個(gè)內存分配的緩沖池(Cache),使用這套機制有如下若

干原因:

1. 系統調用可能不支持任意大小的內存分配。有些系統的系統調用只支持固定大小及其

倍數的內存請求(按頁(yè)分配);這樣的話(huà)對于大量的小內存分類(lèi)來(lái)說(shuō)會(huì )造成浪費。

2. 系統調用申請內存可能是代價(jià)昂貴的。系統調用可能涉及用戶(hù)態(tài)和核心態(tài)的轉換。

3. 沒(méi)有管理的內存分配在大量復雜內存的分配釋放操作下很容易造成內存碎片。

堆和棧的對比

從以上知識可知,棧是系統提供的功能,特點(diǎn)是快速高效,缺點(diǎn)是有限制,數據不靈活

;而棧是函數庫提供的功能,特點(diǎn)是靈活方便,數據適應面廣泛,但是效率有一定降低

。棧是系統數據結構,對于進(jìn)程/線(xiàn)程是唯一的;堆是函數庫內部數據結構,不一定唯一

。不同堆分配的內存無(wú)法互相操作。?臻g分靜態(tài)分配和動(dòng)態(tài)分配兩種。靜態(tài)分配是編

譯器完成的,比如自動(dòng)變量(auto)的分配。動(dòng)態(tài)分配由alloca函數完成。棧的動(dòng)態(tài)分配

無(wú)需釋放(是自動(dòng)的),也就沒(méi)有釋放函數。為可移植的程序起見(jiàn),棧的動(dòng)態(tài)分配操作是

不被鼓勵的!堆空間的分配總是動(dòng)態(tài)的,雖然程序結束時(shí)所有的數據空間都會(huì )被釋放回

系統,但是精確的申請內存/釋放內存匹配是良好程序的基本要素。


可以放一塊思考
堆和棧的生長(cháng)方向恰好相反,
|--------------| 低地址
| 堆 |
|--------------|
| | |
| I |
| |
| ^ |
| 棧 | 高地址
-----------------
所以計算機中的堆和棧經(jīng)常時(shí)放一塊講的


nod 一般不是必要就不要動(dòng)態(tài)創(chuàng )建,最討厭把new出來(lái)的東西當局部變量用,用萬(wàn)了馬上
delete 的做法.

理由
1.棧分配比堆快,只需要一條指令就呢給配所有的局部變量
2.棧不會(huì )出現內存碎片
3。棧對象好管理

當然,某些情況下也要那么寫(xiě),比如
1.對象很大
2.對象需要在某個(gè)特定的時(shí)刻構造或析夠
3.類(lèi)只允許對象動(dòng)態(tài)創(chuàng )建,比如VCL的大多數類(lèi)

當然,必須用堆對象時(shí)也不能躲避


 對于類(lèi)的申明(還沒(méi)有定義)來(lái)說(shuō),可以有限的方式使用它。如我們可以聲明指向該類(lèi)類(lèi)型的指針或引用。允許指針和引用是因為它們都有固定的大小,而與它們指向的對象的大小無(wú)關(guān)。只有到完全定義了該類(lèi)才能對這些指針和引用解引用。
       只有對類(lèi)定義了,才能聲明該類(lèi)類(lèi)型對象。在程序中還沒(méi)有看到類(lèi)定義之前,數據成員只能是該類(lèi)類(lèi)型的指針或引用。 

       當一個(gè)類(lèi)的類(lèi)頭被看到時(shí),它就被視為已經(jīng)聲明了,所以一個(gè)類(lèi)可以有指向自身類(lèi)型的指針或引用作為數據成員。只有一個(gè)類(lèi)的類(lèi)體已經(jīng)完整時(shí),它才被視為已經(jīng)被定義。

       所以可以有如下形式:

    class LinkScreen{

          Screen window;

          LinkScreen *next;

          LinkScreen *prev;

    }
本文地址:http://selenalain.com/thread-3175-1-1.html     【打印本頁(yè)】

本站部分文章為轉載或網(wǎng)友發(fā)布,目的在于傳遞和分享信息,并不代表本網(wǎng)贊同其觀(guān)點(diǎn)和對其真實(shí)性負責;文章版權歸原作者及原出處所有,如涉及作品內容、版權和其它問(wèn)題,我們將根據著(zhù)作權人的要求,第一時(shí)間更正或刪除。
您需要登錄后才可以發(fā)表評論 登錄 | 立即注冊

相關(guān)視頻

關(guān)于我們  -  服務(wù)條款  -  使用指南  -  站點(diǎn)地圖  -  友情鏈接  -  聯(lián)系我們
電子工程網(wǎng) © 版權所有   京ICP備16069177號 | 京公網(wǎng)安備11010502021702
快速回復 返回頂部 返回列表
午夜高清国产拍精品福利|亚洲色精品88色婷婷七月丁香|91久久精品无码一区|99久久国语露脸精品|动漫卡通亚洲综合专区48页