#error的作用是什么?
#error ?指令讓預(yù)處理器發(fā)出一條錯誤信息,并且會中斷編譯過程。下面我們從Linux代碼中抽取出來一小段代碼并做修改得到示例代碼:
這段示例代碼很簡單,當(dāng)RX_BUF_IDX宏的值不為0~3時,在預(yù)處理階段就會通過 #error ?指令輸出一條錯誤提示信息:
"Invalid configuration for 8139_RXBUF_IDX" 下面編譯看一看結(jié)果:
位操作的基本使用
給一個32bit數(shù)據(jù)的位置1,怎么用宏來實現(xiàn)?
#define SET_BIT(x, bit) (x |= (1 << bit)) /* 置位第bit位 */
?
?
?
隱式轉(zhuǎn)換規(guī)則
如下代碼的輸出結(jié)果是?為什么?
#include? 程序輸出結(jié)果為:int main(void) { unsigned int a = 6; int b = -20; if (a + b > 6) printf("a+b大于6 "); else printf("a+b小于6 "); return 0; }
a+b大于6? 原因是因為編譯器會將有符號數(shù)b轉(zhuǎn)換成為一個無符號數(shù),即此處 a+b 等價于 a+(unsigned int)b 。 該程序運行在32bit環(huán)境下,b的值為 0xFFFFFFFF-20+1 = 4294967276 ,即a+b將遠(yuǎn)遠(yuǎn)大于6。 C 語言按照一定的規(guī)則來進(jìn)行此類運算的轉(zhuǎn)換,這種規(guī)則稱為 正常算術(shù)轉(zhuǎn)換 ,轉(zhuǎn)換的順序為:
double>float>unsigned long>long>unsigned int>int? 即操作數(shù)類型排在后面的與操作數(shù)類型排在前面的進(jìn)行運算時,排在后面的類型將 隱式轉(zhuǎn)換 為排在前面的類型。
typedef與define的區(qū)別
(1)#define之后不帶分號,typedef之后帶分號。 (2)#define可以使用其他類型說明符對宏類型名進(jìn)行擴(kuò)展,而 typedef 不能這樣做。如:
#define INT1 int unsigned INT1 n; //沒問題 typedef int INT2; unsigned INT2 n; //有問題? INT1可以使用類型說明符unsigned進(jìn)行擴(kuò)展,而INT2不能使用unsigned進(jìn)行擴(kuò)展。 (3)在連續(xù)定義幾個變量的時候,typedef 能夠保證定義的所有變量均為同一類型,而 #define 則無法保證。如:
#define PINT1 int*; P_INT1 p1,p2; //即int *p1,p2; typedet int* PINT2; P_INT2 p1,p2; //p1、p2 類型相同? PINT1定義的p1與p2類型不同,即p1為指向整形的指針變量,p2為整形變量;PINT2定義的p1與p2類型相同,即都是指向 int 類型的指針。
寫一個MAX宏
#define MAX(x,y) ((x) > (y) ? (x) : (y))? 使用括號把參數(shù)括起來可以解決了運算符優(yōu)先級帶來的問題。這樣的MAX宏基本可以滿足日常使用,但是還有更嚴(yán)謹(jǐn)?shù)母呒墝懛ā?感興趣的可參考文章: https://www.zhaixue.cc/c-arm/c-arm-express.html
死循環(huán)
嵌入式系統(tǒng)中經(jīng)常要用到無限循環(huán),你怎么樣用C編寫死循環(huán)呢? (1)while
while(1) { }? (2)for
for(;;) { }? (3)goto
Loop: … goto Loop;?static的作用
在C語言中,關(guān)鍵字static有三個明顯的作用: 1、在函數(shù)體修飾變量 一個被聲明為靜態(tài)的變量在這一函數(shù)被調(diào)用過程中維持其值不變。 2、 在模塊內(nèi)(但在函數(shù)體外)修飾變量 一個被聲明為靜態(tài)的變量可以被模塊內(nèi)所用函數(shù)訪問,但不能被模塊外其它函數(shù)訪問。它是一個本地的全局變量。 3、在模塊內(nèi)修飾函數(shù) 一個被聲明為靜態(tài)的函數(shù)只可被這一模塊內(nèi)的其它函數(shù)調(diào)用。那就是,這個函數(shù)被限制在聲明它的模塊的本地范圍內(nèi)使用。
const的作用
下面的聲明都是什么意思:
?
const int a; int const a; const int *a; int * const a; int const * a const;前兩個的作用是一樣,a是一個常整型數(shù)。
第三個意味著a是一個指向常整型數(shù)的指針(也就是,整型數(shù)是不可修改的,但指針可以)。
第四個意思a是一個指向整型數(shù)的常指針(也就是說,指針指向的整型數(shù)是可以修改的,但指針是不可修改的)。
最后一個意味著a是一個指向常整型數(shù)的常指針(也就是說,指針指向的整型數(shù)是不可修改的,同時指針也是不可修改的)。
volatile的作用
以下內(nèi)容來自百度百科: 一個定義為volatile的變量是說這變量可能會被意想不到地改變,這樣,編譯器就不會去假設(shè)這個變量的值了。精確地說就是,優(yōu)化器在用到這個變量時必須每次都小心地重新讀取這個變量的值,而不是使用保存在寄存器里的備份。下面是volatile變量的幾個例子: 1). 并行設(shè)備的硬件寄存器(如:狀態(tài)寄存器) 2). 一個中斷服務(wù)子程序中會訪問到的非自動變量(Non-automatic variables) 3). 多線程應(yīng)用中被幾個任務(wù)共享的變量 回答不出這個問題的人是不會被雇傭的。我認(rèn)為這是區(qū)分C程序員和嵌入式系統(tǒng)程序員的最基本的問題。嵌入式系統(tǒng)程序員經(jīng)常同硬件、中斷、RTOS等等打交道,所用這些都要求volatile變量。不懂得volatile內(nèi)容將會帶來災(zāi)難。 假設(shè)被面試者正確地回答了這是問題(嗯,懷疑這否會是這樣),我將稍微深究一下,看一下這家伙是不是直正懂得volatile完全的重要性。 1). 一個參數(shù)既可以是const還可以是volatile嗎?解釋為什么。 2). 一個指針可以是volatile 嗎?解釋為什么。 3). 下面的函數(shù)有什么錯誤:
?
int square(volatile int *ptr) { return *ptr * *ptr; }? 下面是答案: 1). 是的。一個例子是只讀的狀態(tài)寄存器。它是volatile因為它可能被意想不到地改變。它是const因為程序不應(yīng)該試圖去修改它。 2). 是的。盡管這并不很常見。一個例子是當(dāng)一個中服務(wù)子程序修該一個指向一個buffer的指針時。 3). 這段代碼的有個惡作劇。這段代碼的目的是用來返指針 *ptr 指向值的平方,但是,由于 *ptr 指向一個volatile型參數(shù),編譯器將產(chǎn)生類似下面的代碼:
int square(volatile int* &ptr)//這里參數(shù)應(yīng)該申明為引用,不然函數(shù)體里只會使用副本,外部沒法更改 { int a,b; a = *ptr; b = *ptr; return a*b; }? 由于*ptr的值可能在兩次取值語句之間發(fā)生改變,因此a和b可能是不同的。結(jié)果,這段代碼可能返回的不是你所期望的平方值!正確的代碼如下:
long square(volatile int*ptr) { int a; a = *ptr; return a*a; }?變量定義
用變量a給出下面的定義:
a)一個整型數(shù)
b) 一個指向整型數(shù)的指針
c) 一個指向指針的的指針,它指向的指針是指向一個整型數(shù)
d) 一個有10個整型數(shù)的數(shù)組
e) 一個有10個指針的數(shù)組,該指針是指向一個整型數(shù)的:
f) 一個指向有10個整型數(shù)數(shù)組的指針
g) 一個指向函數(shù)的指針,該函數(shù)有一個整型參數(shù)并返回一個整型數(shù)
h) 一個有10個函數(shù)指針的數(shù)組,該指針指向一個函數(shù),該函數(shù)有一個整型參數(shù)并返回一個整型數(shù)
a) int a; b) int *a; c) int **a; d) int a[10]; e) int *a[10]; f) int ( *a)[10]; g) int ( *a)(int); h) int ( *a[10])(int);
中斷函數(shù)
中斷是嵌入式系統(tǒng)中重要的組成部分,這導(dǎo)致了很多編譯開發(fā)商提供一種擴(kuò)展—讓標(biāo)準(zhǔn)C支持中斷。具代表事實是,產(chǎn)生了一個新的關(guān)鍵字 __ interrupt 。 下面的代碼就使用了 __ interrupt 關(guān)鍵字去定義了一個中斷服務(wù)子程序(ISR),請評論一下這段代碼的。
__interrupt double compute_area (double radius) { double area = PI * radius * radius; printf(" Area = %f", area); return area; }? 1). ISR 不能返回一個值。 2). ISR 不能傳遞參數(shù)。 3). 在許多的處理器/編譯器中,浮點一般都是不可重入的。有些處理器/編譯器需要讓額處的寄存器入棧,有些處理器/編譯器就是不允許在ISR中做浮點運算。此外,ISR應(yīng)該是短而有效率的,在ISR中做浮點運算是不明智的。 4). 與第三點一脈相承,printf()經(jīng)常有重入和性能上的問題。
編輯:黃飛
?
評論