【1】用#define聲明一個常數(shù),用以表示一年中有多少秒
#define SECONDS_PER_YEAR (60*60*24*365)UL
說明:首先,末尾#define語法末尾不能有分號;
其次,計算式最好帶括號;
第三,這個表達式會使16位機的整型數(shù)溢出,因此需要用長整型符號L告訴編譯器這個常數(shù)是長整型數(shù),末尾用UL(無符號長整型)。
【2】用C編寫死循環(huán)
第一種方案:while(1){}
第二種方案:for(;;){}
第三種方案:Loop:
goto Loop; //這種方案是用匯編寫的
【3】訪問特定內(nèi)存位置:
在某工程中,一個整型變量的絕對地址是0x67a9,請將其設(shè)置為0xaa55,并且已知編譯器是一個純粹的ANSI編譯器,請編寫代碼
int* ptr;
ptr=(int*)0x67a9;
*ptr=0xaa55;
【4】對中斷服務(wù)代碼的評論
以上程序有如下幾個錯誤:
1、ISR不能返回一個值;
2、ISR不能傳遞參數(shù),即不能有形參;
3、在許多處理器或編譯器中,浮點數(shù)一般是不可重入的。有些處理器或編譯器需要使用額外的寄存器入棧,有些處理器或編譯器是不允許在ISR中做浮點運算。此外,ISR應(yīng)該是短而有效率的,在ISR中做浮點運算是不明智的;
4、printf()經(jīng)常出現(xiàn)重入和性能上的問題,
【5】對整數(shù)自動轉(zhuǎn)換原則的理解
C語言中,整數(shù)自動轉(zhuǎn)換原則是:當表達式中同時存在有符號和無符號類型時,所有的操作數(shù)都自動轉(zhuǎn)換成無符號類型。因此,上面程序中,第5行,a+b,a是無符號整型,b是有符號整型,二者相加,則b自動轉(zhuǎn)換成無符號整型,-20變成了一個非常大的正整數(shù),那么顯然,此時a+b》6是成立的,因此,上面程序最終輸出的結(jié)果是“》6”。
【6】關(guān)鍵字static的作用
1、在函數(shù)體內(nèi),局部的stati變量。作用域在函數(shù)體內(nèi),生存期卻為程序的生命周期。一個被聲明為靜態(tài)的變量在這一函數(shù)被調(diào)用過程中維持其值不變,即本次訪問該變量時訪問到的是上次調(diào)用后的值。因為它被分配在靜態(tài)存儲區(qū)內(nèi),函數(shù)結(jié)束調(diào)用后并不釋放單元,但是在其它的作用域無法訪問。當再次訪問這個函數(shù)時,這個局部的靜態(tài)變量還存活,因此訪問到的是上次調(diào)用后的值。
2、在文件模塊內(nèi)(但在函數(shù)體外),一個被聲明為靜態(tài)的全局變量,可以被模塊內(nèi)所有函數(shù)訪問,但不能被模塊外其它函數(shù)訪問。它是一個本地的全局變量。
3、在文件模塊內(nèi),一個被聲明為靜態(tài)的函數(shù)只可以被這個模塊內(nèi)的其它函數(shù)調(diào)用。即這個函數(shù)被限制在聲明它的本地范圍內(nèi)。
【7】與全局對象相比,使用靜態(tài)數(shù)據(jù)成員有什么優(yōu)勢
1、靜態(tài)數(shù)據(jù)成員沒有進入程序的全局名字空間,因此不存在與程序中其它全局名字沖突的問題。
2、使用靜態(tài)數(shù)據(jù)成員可以隱藏信息,因為靜態(tài)數(shù)據(jù)成員可以是private成員,而全局變量不能。
【8】關(guān)鍵字volatile的含義
定義為volatile的變量可能會被意想不到地改變,這樣編譯器就不會去假設(shè)這個變量的值。準確地說,優(yōu)化器在用到volatile變量時必須小心地重新讀取該變量的值,而不是使用保存在寄存器里的備份。使用volatile變量的地方如:
1、并行設(shè)備的硬件寄存器(如:狀態(tài)寄存器)。
2、一個中斷服務(wù)子程序中會訪問到的非自動變量。
3、多線程應(yīng)用中被幾個任務(wù)共享的變量。
【9】判斷處理器使用Big_endian還是Little_endian模式存儲數(shù)據(jù)
編寫一個函數(shù),若處理器使用Big_endian模式存數(shù)數(shù)據(jù),則返回0;若是用Little_endian模式存儲數(shù)據(jù),則返回1。
分析:首先,應(yīng)該了解Little_endian和Big_endian模式有所了解,采用Little_endian模式的CPU對操作數(shù)的存儲方式是從低字節(jié)到高字節(jié),而Big_endian模式對操作數(shù)的存儲方式是從高字節(jié)到低字節(jié)。
例如,16位數(shù)0x1234在Little_endian模式CPU內(nèi)存中的存放方式(假設(shè)從地址0x4000開始存放)為:
0x4000: 0x34
0x4001: 0x12
而在Big_endian模式CPU內(nèi)存中的存放方式為:
0x4000: 0x12
0x4001: 0x34
32位寬的數(shù)0x12345678在Little_endian模式CPU內(nèi)存中的存放方式為:
0x4000: 0x78
0x4001: 0x56
0x4002: 0x34
0x4003: 0x12
而在Big_endian模式CPU內(nèi)存中存儲方式為:
0x4000: 0x12
0x4001: 0x34
0x4002: 0x56
0x4003: 0x78
該函數(shù)為:
在聯(lián)合體中定義了兩個成員int和char,而聯(lián)合體的大小=sizeof(int)=4,因此該聯(lián)合體在內(nèi)存中占4個字節(jié)的大小,假設(shè)占用的內(nèi)存地址為:0x1000~0x1003,那么當給a賦值1時,如果按Little_endian方式存放該數(shù)據(jù),則:
0x1000: 0x01
0x1001: 0x00
0x1002: 0x00
0x1003: 0x00
那么這個數(shù)值1應(yīng)該存放于地址0x1000中
而聯(lián)合體有一個特性:成員都從低地址開始存放,所以當c.b=1時,那就證明數(shù)值1是存儲于地址0x1000中的,那么久可以證明是Little_endian方式存儲。
如果按Big_endian方式存放a的數(shù)值1,則
0x1000: 0x00
0x1001: 0x00
0x1002: 0x00
0x1003: 0x01
由聯(lián)合體的特性可知,當以Big_endian方式存儲的時候,c.b=0
【10】判斷處理器字長
unsigned int CompareZero=~0
cout《《hex《《CompareZero《《endl;
【11】找錯(對靜態(tài)成員與非靜態(tài)成員的理解)
上面程序中,i為靜態(tài)成員變量,func2()為靜態(tài)成員函數(shù)
第9行,test(int a):i(1),j(a) {} 根據(jù)規(guī)定,初始化列表的初始化順序 應(yīng)該與 變量聲明的順序一致,而不是按照出現(xiàn)在初始化列表中的順序,從第7、8行可以看到,變量聲明順序先是i,然后再j,那么在第9行中,也應(yīng)該先初始化i,再初始化j,那么此時應(yīng)該i=1,j=a=2,這樣看似沒有錯,但是,忽略了一個細節(jié),i是靜態(tài)成員變量。
為了與非靜態(tài)成員變量相區(qū)別,i是不能再類的內(nèi)部被初始化的。
可以在類的外部進行初始化,如,先把第9行改為,test(int a):j(a) {}
然后再在第13行,添加:int test::i=1;
第16行,定義func2函數(shù),首先該函數(shù)為靜態(tài)成員函數(shù),它想訪問靜態(tài)成員變量i,以及普通變量j,但是靜態(tài)成員函數(shù)只能訪問靜態(tài)成員變量,并不能訪問非靜態(tài)成員,因此無法訪問j,此行應(yīng)該改為:
void test::func2() {cout《《i《《endl;}
需要注意的是:
1、靜態(tài)數(shù)據(jù)成員必須在類外面初始化,以示與普通數(shù)據(jù)成員的區(qū)別。
2、靜態(tài)數(shù)據(jù)成員以及靜態(tài)函數(shù)成員,不屬于類的對象,因此沒有this指針,也就無法調(diào)用類的非靜態(tài)成員,它是為類的所有的對象所共享。
評論
查看更多