程式設計技巧之嵌入式C語言完全學習筆記及案例[圖]

minemi發表於2018-08-15

程式設計技巧之嵌入式C語言完全學習筆記及案例[圖]
1、經典入門:hello world
1.1、概念:
*原始檔:原始檔即原始碼檔案,C語言原始檔字尾名是.c。
*標頭檔案:標頭檔案字尾名為.h(head,頭),C語言程式碼由原始檔和標頭檔案組成。
*關鍵字:關鍵字是C語言徵用了的一些字,這些字在C語言中代表特殊含義,已經被C語言定義好了,輪不到我們用了。每個關鍵字都有自己特定的含義,我們必須搞懂每個關鍵字的所有含義和用法,否則就看不懂C語言程式。
*註釋:C語言中註釋以//開頭,或者/* */,註釋是給程式設計師看的,不是給機器看的。也
就是說,程式設計師寫註釋給其他人看,以讓人明白自己為什麼要這麼寫。但是編譯器編譯程式的時候是忽略註釋內容的,所以機器根本看不見註釋,也不理註釋。
*符號:C語言程式中包含很多符號,如; : , + () {} *等等,各種符號都有自己的含義,必須
搞明白各種符號的含義,才能看懂C語言程式。
*變數:會變化的量。C語言程式中用變數來進行計算。
*函式:函式是C語言的一個基本組成單位,一個C語言程式其實就是由很多函式組成的,每個函式用來完成一定的功能,函式可以呼叫別的函式來完成功能。函式的標誌是().C語言中有一個特殊的函式叫main,這個函式是整個程式的內定的入口,也就是說整個C語言程式是從main函式開始執行的,其他的函式都是直接或者間接被main呼叫。

程式設計技巧之嵌入式C語言完全學習筆記及案例[圖]

1.2、C語言寫程式碼步驟:
第一步:編輯原始碼(使用vi或者其他編輯器)
第二步:編譯。編譯就是用編譯器把源程式轉化成可執行程式的過程,編譯要用到編譯器。我們在linux中使用編譯器一般是gcc。
譬如:gcc hello.c    把當前目錄下hello.c檔案編譯,得到的可執行檔名字叫a.out
也可以自己指定編譯後生成的可執行程式的名字,使用gcc hello.c -o hello
第三步:執行編譯生成的可執行程式,執行方式是./hello
第四步:除錯。當你執行後發現程式結果不對,不是自己想要的,這時候就是返回來看原始碼哪裡不對。然後修改,再編譯執行,再看結果。如此迴圈直接結果正確。
C語言關鍵字:
include(包含)                標頭檔案包含
int(integer,整數)        用來表示一個整數的型別叫整形。
float(浮點型)                用來表示小數的型別
char(character,字元)        字元型資料型別
return(返回)                函式返回    
VMWare共享資料夾使用
嵌入式C語言完全學習筆記進階篇:
1、資料型別
1.1、基本資料型別
資料型別分2類:基本資料型別+複合型別
基本型別:char short int long float double
複合型別:陣列 結構體 共用體 類(C語言沒有類,C++有)
1.1.1、記憶體佔用與sizeof運算子
資料型別就好像一個一個的模子,這個模子例項化出C語言的變數。變數儲存在記憶體中,需要佔用一定的記憶體空間。一個變數佔用多少空間是由變數的資料型別決定的。
每種資料型別,在不同的機器平臺上佔用記憶體是不同的。我們一般講的時候都是以32位CPU為預設硬體平臺來描述:
char         1位元組        8位
short         2位元組        16位
int         4位元組        32位
long         4位元組        32位
float         4位元組        
double        8位元組        
1.1.2、有符號數和無符號數
對於char short int long等整形型別的數,都分有符號有無符號數。
而對於float和double這種浮點型數來說,只有有符號數,沒有無符號數。
對於C語言來說,數(也就是變數)是儲存在記憶體中一個一個的格子中的。儲存的時候是以二進位制方式儲存的。對於有符號數和無符號數來說,儲存方式不同的。譬如對於int來說
unsigned int 無符號數,32位(4位元組)全部用來存數的內容 所以表示的數的範圍
是0 ~ 4294967295(2^32 - 1)
signed int   有符號數,32位中最高位用來存符號(0表示正數,1表示負數),剩餘的31位用
來存資料。所以可以表示的數的範圍是     -2147483648(2^32)    ~ 2147483647(2^31 - 1)
結論:從絕對數值來說,無符號數所表示的範圍要大一些。因為有符號數使用1個二進位制位來表示正負號。
1.1.3、整形數和浮點型數儲存方式上的不同
對於float和double這種浮點型別的數,它在記憶體中的儲存方式和整形數不一樣。所以float和
int相比,雖然都是4位元組,但是在記憶體中儲存的方式完全不同。所以同一個4位元組的記憶體,如果儲存時是按照int存放的,取的時候一定要按照int型方式去取。如果存的時候和取的時候理解的方式不同,那資料就完全錯了。
備註:詳細的數制儲存可以查詢資料:計算機原碼、反碼、補碼等知識。
總結:存取方式上主要有兩種,一種是整形一種是浮點型,這兩種存取方式完全不同,沒有任何關聯,所以是絕對不能隨意改變一個變數的存取方式。在整形和浮點型之內,譬如說4種整形char、short、int、long只是範圍大小不同而已,儲存方式是一模一樣的。float和double儲存原理是相同的,方式上有差異,導致了能表示的浮點型的範圍和精度不同。
1.2、空型別(關鍵字void)
C語言中的void型別,代表任意型別,而不是空的意思。任意型別的意思不是說想變成誰就變成誰,而是說它的型別是未知的,是還沒指定的。
void *    是void型別的指標。void型別的指標的含義是:這是一個指標變數,該指標指向一個
void型別的數。void型別的數就是說這個數有可能是int,也有可能是float,也有可能是個結構體,哪種型別都有可能,只是我當前不知道。
void型指標的作用就是,程式不知道那個變數的型別,但是程式設計師自己心裡知道。程式設計師如何知道?當時給這個變數賦值的時候是什麼型別,現在取的時候就還是什麼型別。這些型別對不對,能否相容,完全由程式設計師自己負責。編譯器看到void就沒辦法幫你做型別檢查了。
在函式的引數列表和返回值中,void代表的含義是:
一個函式形參列表為void,表示這個函式呼叫時不需要給它傳參。
返回值型別是void,表示這個函式不會返回一個有意義的返回值。所以呼叫者也不要想著去使用該返回值。
C語言設計基本理念:
C語言相信程式設計師永遠是對的,C語言相信程式設計師都是高手,C語言賦予了程式設計師最大的權利。所以C語言的程式設計師必須自己對程式的對錯負責,必須隨時腦袋清楚,知道自己在幹嘛。
1.3、資料型別轉換
C語言中有各種資料型別,寫程式時需要定義各種型別的變數。這些變數需要參與運算。C語言有一個基本要求就是:不同型別的變數是不能直接運算的。
也就是說,int和float型別的變數不能直接加減等運算。你要運算,必須先把兩種型別轉成相同的型別才可以。
1.3.1、隱式轉換
隱式轉換就是自動轉換,是C語言預設會進行的,不用程式設計師干涉。
C語言的理念:隱式型別轉換預設朝精度更高、範圍更大的方向轉換。
1.3.2、強制型別轉換
C語言預設不會這麼做,但是程式設計師我想這麼做,所以我強制這麼做了。
1.4、C語言與bool型別
C語言中原生型別沒有bool,C++中有。在C語言中如果需要使用bool型別,可以用int來代替。
很多程式碼體系中,用以下巨集定義來定義真和假
#define TRUE    1
#define FALSE    0
2、變數和常量
2.1、變數
變數,指的是在程式執行過程中,可以通過程式碼使它的值改變的量。
2.1.1、區域性變數
定義在函式中的變數,就叫區域性變數。
2.1.1.1、普通區域性變數(auto)
普通的區域性變數定義時直接定義,或者在定義前加auto關鍵字
void func1(void)
{
int i = 1;
i++;
printf("i = %d.\n", i);
}
區域性變數i的解析:
在連續三次呼叫func1中,每次呼叫時,在進入函式func1後都會創造一個新的變數i,並且給它賦初值1,然後i++時加到2,然後printf輸出時輸出2.然後func1本次呼叫結束,結束時同時殺死本次創造的這個i。這就是區域性變數i的整個生命週期。
下次再呼叫該函式func1時,又會重新創造一個i,經歷整個程式運算,最終在函式執行完退出時再次被殺死。
2.1.1.2、靜態區域性變數(static)
靜態區域性變數定義時前面加static關鍵字。
總結:
1、靜態區域性變數和普通區域性變數不同。靜態區域性變數也是定義在函式內部的,靜態區域性變數定義時前面要加static關鍵字來標識,靜態區域性變數所在的函式在多呼叫多次時,只有第一次才經歷變數定義和初始化,以後多次在呼叫時不再定義和初始化,而是維持之前上一次呼叫時執行後這個變數的值。本次接著來使用。
2、靜態區域性變數在第一次函式被呼叫時創造並初始化,但在函式退出時它不死亡,而是保持其值等待函式下一次被呼叫。下次呼叫時不再重新創造和初始化該變數,而是直接用上一次留下的值為基礎來進行操作。
3、靜態區域性變數的這種特性,和全域性變數非常類似。它們的相同點是都創造和初始化一次,以後呼叫時值保持上次的不變。不同點在於作用域不同
2.1.1.4、register關鍵字
register(暫存器),C語言的一個關鍵字
register int i = 3;
總結:register型別的區域性變數表現上和auto是一樣的,這東西基本沒用,知道就可以了。register被稱為:C語言中最快的變數。C語言的執行時環境承諾,會盡量將register型別的變數放到暫存器中去執行(普通的變數是在記憶體中),所以register型別的變數訪問速度會快很多。但是它是有限制的:首先暫存器數目是有限的,所以register型別的變數不能太多;其次register型別變數在資料型別上有限制,譬如你就不能定義double型別的register變數。一般只在核心或者啟動程式碼中,需要反覆使用同一個變數這種情況下才會使用register型別變數。
2.1.2、全域性變數
定義在函式外面的變數,就叫全域性變數。
2.1.2.1、普通全域性變數
普通全域性變數就是平時使用的,定義前不加任何修飾詞。普通全域性變數可以在各個檔案中使
用,可以在專案內別的.c檔案中被看到,所以要確保不能重名。
2.1.2.2、靜態全域性變數
靜態全域性變數就是用來解決重名問題的。靜態全域性變數定義時在定義前加static關鍵字,
告訴編譯器這個變數只在當前本檔案內使用,在別的檔案中絕對不會使用。這樣就不用擔心重名問題。所以靜態的全域性變數就用在我定義這個全域性變數並不是為了給別的檔案使用,本來就是給我這個檔案自己使用的。
2.1.1.3、跨檔案引用全域性變數(extern)
就是說,你在一個程式的多個.c原始檔中,可以在一個.c檔案中定義全域性變數g_a,並且可以在別的另一個.c檔案中引用該變數g_a(引用前要宣告)

函式和全域性變數在C語言中可以跨檔案引用,也就是說他們的連線範圍是全域性的,具有檔案連線屬性,愛的教育讀書筆記(http://www.simayi.net/dushubiji/6047.html)及心得感悟,總之意思就是全域性變數和函式是可以跨檔案看到的(直接影響就是,我在a.c和b.c中各自定義了一個函式func,名字相同但是內容不同,編譯報錯。

區域性變數和全域性變數的對比:
1、定義同時沒有初始化,則區域性變數的值是隨機的,而全域性變數的值是預設為0.
2、使用範圍上:全域性變數具有檔案作用域,而區域性變數只有程式碼塊作用域。
3、生命週期上:全域性變數是在程式開始執行之前的初始化階段就誕生,到整個程式結束退出的時候才死亡;而區域性變數在進入區域性變數所在的程式碼塊時誕生,在該程式碼塊退出的時候死亡。
4、變數分配位置:全域性變數分配在資料段上,而區域性變數分配在棧上。
判斷一個變數能不能使用,有沒有定義,必須注意兩點:第一,該變數定義的作用域是否在當前有效,是否包含當前位置;第二,變數必須先定義後使用。所以變數引用一定要在變數定義之前。

相關文章