當(dāng)前位置:首頁(yè) > 公眾號(hào)精選 > 嵌入式大雜燴
[導(dǎo)讀]關(guān)注「Linux大陸」,一起進(jìn)步!#error的作用是什么?#error?指令讓預(yù)處理器發(fā)出一條錯(cuò)誤信息,并且會(huì)中斷編譯過(guò)程。下面我們從Linux代碼中抽取出來(lái)一小段代碼并做修改得到示例代碼:這段示例代碼很簡(jiǎn)單,當(dāng)RX_BUF_IDX宏的值不為0~3時(shí),在預(yù)處理階段就會(huì)通過(guò)#er...

關(guān)注Linux大陸」,一起進(jìn)步!

#error的作用是什么?

#error ?指令讓預(yù)處理器發(fā)出一條錯(cuò)誤信息,并且會(huì)中斷編譯過(guò)程。下面我們從Linux代碼中抽取出來(lái)一小段代碼并做修改得到示例代碼:

這段示例代碼很簡(jiǎn)單,當(dāng)RX_BUF_IDX宏的值不為0~3時(shí),在預(yù)處理階段就會(huì)通過(guò) #error ?指令輸出一條錯(cuò)誤提示信息:

"Invalid configuration for 8139_RXBUF_IDX"

下面編譯看一看結(jié)果:

推薦文章:認(rèn)識(shí)認(rèn)識(shí)#pragma、#error指令

位操作的基本使用

給一個(gè)32bit數(shù)據(jù)的位置1,怎么用宏來(lái)實(shí)現(xiàn)?

#define?SET_BIT(x,?bit)?(x?|=?(1?</*?置位第bit位?*/
推薦文章:C語(yǔ)言、嵌入式位操作精華技巧大匯總

隱式轉(zhuǎn)換規(guī)則

如下代碼的輸出結(jié)果是?為什么?

#include?
int?main(void)
{
?unsigned?int?a?=?6;
?int?b?=?-20;

?if?(a? ?b?>?6)
??printf("a b大于6\n");
?else
??printf("a b小于6\n");

?return?0;
}
程序輸出結(jié)果為:

a b大于6
原因是因?yàn)榫幾g器會(huì)將有符號(hào)數(shù)b轉(zhuǎn)換成為一個(gè)無(wú)符號(hào)數(shù),即此處 a b 等價(jià)于 a (unsigned int)b 。

該程序運(yùn)行在32bit環(huán)境下,b的值為 0xFFFFFFFF-20 1 = 4294967276 ,即a b將遠(yuǎn)遠(yuǎn)大于6。

C 語(yǔ)言按照一定的規(guī)則來(lái)進(jìn)行此類運(yùn)算的轉(zhuǎn)換,這種規(guī)則稱為 正常算術(shù)轉(zhuǎn)換 ,轉(zhuǎn)換的順序?yàn)椋?/p>double>float>unsigned?long>long>unsigned?int>int
即操作數(shù)類型排在后面的與操作數(shù)類型排在前面的進(jìn)行運(yùn)算時(shí),排在后面的類型將 隱式轉(zhuǎn)換 為排在前面的類型。

推薦文章:關(guān)于有符號(hào)數(shù)與無(wú)符號(hào)數(shù)的一些總結(jié)

typedef與define的區(qū)別

(1)#define之后不帶分號(hào),typedef之后帶分號(hào)。

(2)#define可以使用其他類型說(shuō)明符對(duì)宏類型名進(jìn)行擴(kuò)展,而 typedef 不能這樣做。如:

#define?INT1?int
unsigned?INT1?n;??//沒(méi)問(wèn)題
typedef?int?INT2;
unsigned?INT2?n;??//有問(wèn)題
INT1可以使用類型說(shuō)明符unsigned進(jìn)行擴(kuò)展,而INT2不能使用unsigned進(jìn)行擴(kuò)展。

(3)在連續(xù)定義幾個(gè)變量的時(shí)候,typedef 能夠保證定義的所有變量均為同一類型,而 #define 則無(wú)法保證。如:

#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 類型的指針。

推薦文章:#define與typedef的區(qū)別?

寫一個(gè)MAX宏

#define?MAX(x,y)?((x)?>?(y)???(x)?:?(y))
使用括號(hào)把參數(shù)括起來(lái)可以解決了運(yùn)算符優(yōu)先級(jí)帶來(lái)的問(wèn)題。這樣的MAX宏基本可以滿足日常使用,但是還有更嚴(yán)謹(jǐn)?shù)母呒?jí)寫法。

感興趣的可參考文章:

https://www.zhaixue.cc/c-arm/c-arm-express.html

死循環(huán)

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

(1)while

while(1)?{?}
(2)for

for(;;)?{?}
(3)goto

Loop:



goto?Loop;

static的作用

在C語(yǔ)言中,關(guān)鍵字static有三個(gè)明顯的作用:

1、在函數(shù)體修飾變量

一個(gè)被聲明為靜態(tài)的變量在這一函數(shù)被調(diào)用過(guò)程中維持其值不變。

2、 在模塊內(nèi)(但在函數(shù)體外)修飾變量

一個(gè)被聲明為靜態(tài)的變量可以被模塊內(nèi)所用函數(shù)訪問(wèn),但不能被模塊外其它函數(shù)訪問(wèn)。它是一個(gè)本地的全局變量。

3、在模塊內(nèi)修飾函數(shù)

一個(gè)被聲明為靜態(tài)的函數(shù)只可被這一模塊內(nèi)的其它函數(shù)調(diào)用。那就是,這個(gè)函數(shù)被限制在聲明它的模塊的本地范圍內(nèi)使用。

const的作用

下面的聲明都是什么意思:

const?int?a;?
int?const?a;
const?int?*a;
int?*?const?a;
int?const?*?a?const;
  • 前兩個(gè)的作用是一樣,a是一個(gè)常整型數(shù)。
  • 第三個(gè)意味著a是一個(gè)指向常整型數(shù)的指針(也就是,整型數(shù)是不可修改的,但指針可以)。
  • 第四個(gè)意思a是一個(gè)指向整型數(shù)的常指針(也就是說(shuō),指針指向的整型數(shù)是可以修改的,但指針是不可修改的)。
  • 最后一個(gè)意味著a是一個(gè)指向常整型數(shù)的常指針(也就是說(shuō),指針指向的整型數(shù)是不可修改的,同時(shí)指針也是不可修改的)。

volatile的作用

以下內(nèi)容來(lái)自百度百科:

一個(gè)定義為volatile的變量是說(shuō)這變量可能會(huì)被意想不到地改變,這樣,編譯器就不會(huì)去假設(shè)這個(gè)變量的值了。精確地說(shuō)就是,優(yōu)化器在用到這個(gè)變量時(shí)必須每次都小心地重新讀取這個(gè)變量的值,而不是使用保存在寄存器里的備份。下面是volatile變量的幾個(gè)例子:

1). 并行設(shè)備的硬件寄存器(如:狀態(tài)寄存器)

2). 一個(gè)中斷服務(wù)子程序中會(huì)訪問(wèn)到的非自動(dòng)變量(Non-automatic variables)

3). 多線程應(yīng)用中被幾個(gè)任務(wù)共享的變量

回答不出這個(gè)問(wèn)題的人是不會(huì)被雇傭的。我認(rèn)為這是區(qū)分C程序員和嵌入式系統(tǒng)程序員的最基本的問(wèn)題。嵌入式系統(tǒng)程序員經(jīng)常同硬件、中斷、RTOS等等打交道,所用這些都要求volatile變量。不懂得volatile內(nèi)容將會(huì)帶來(lái)災(zāi)難。

假設(shè)被面試者正確地回答了這是問(wèn)題(嗯,懷疑這否會(huì)是這樣),我將稍微深究一下,看一下這家伙是不是直正懂得volatile完全的重要性。

1). 一個(gè)參數(shù)既可以是const還可以是volatile嗎?解釋為什么。

2). 一個(gè)指針可以是volatile 嗎?解釋為什么。

3). 下面的函數(shù)有什么錯(cuò)誤:

int?square(volatile?int?*ptr)
{
?return?*ptr?*?*ptr;
}
下面是答案:

1). 是的。一個(gè)例子是只讀的狀態(tài)寄存器。它是volatile因?yàn)樗赡鼙灰庀氩坏降馗淖儭K莄onst因?yàn)槌绦虿粦?yīng)該試圖去修改它。

2). 是的。盡管這并不很常見。一個(gè)例子是當(dāng)一個(gè)中服務(wù)子程序修該一個(gè)指向一個(gè)buffer的指針時(shí)。

3). 這段代碼的有個(gè)惡作劇。這段代碼的目的是用來(lái)返指針 *ptr 指向值的平方,但是,由于 *ptr 指向一個(gè)volatile型參數(shù),編譯器將產(chǎn)生類似下面的代碼:

int?square(volatile?int*?
本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
關(guān)閉
關(guān)閉