C語言深度剖析-筆記

新一發表於2018-01-04

關鍵字:

C語言關鍵字32個:

關鍵字                                         意 義

auto                           宣告自動變數,預設時編譯器一般預設為 auto

int                               宣告整型變數

double                       宣告雙精度變數

long                            宣告長整型變數

char                            宣告字元型變數

float                           宣告浮點型變數

short                          宣告短整型變數

signed                        宣告有符號型別變數

unsigned                   宣告無符號型別變數

struct                         宣告結構體變數

union                          宣告聯合資料型別

enum                         宣告列舉型別

static                         宣告靜態變數

switch                        用於開關語句

case                           開關語句分支

default                       開關語句中的“其他”分支

break                         跳出當前迴圈

register                     宣告暫存器變數

const                          宣告只讀變數

volatile                      說明變數在程式執行中可被隱含地改變

typedef                      用以給資料型別取別名(當然還有其他作用)

extern                        宣告變數是在其他檔案正宣告(也可以看做是引用變數)

return                        子程式返回語句(可以帶引數,也可不帶引數)

void                            宣告函式無返回值或無引數,宣告空型別指標

continue                    結束當前迴圈,開始下一輪迴圈

do                               迴圈語句的迴圈體

while                           迴圈語句的迴圈條件

if                                  條件語句

else                            條件語句否定分支(與 if 連用)

for                               一種迴圈語句(可意會不可言傳)

goto                           無條件跳轉語句

sizeof                         計算物件所佔記憶體空間大小

 

auto:編譯器在預設的預設情況下,所有變數都是auto的。

register:這個關鍵字請求編譯器儘可能的將變數存在 CPU 內部暫存器中而不是通過內

存定址訪問以提高效率。

register 變數必須是一個單個的值,並且其長度應小於或等於整型的長度。 而且 register 變數可能不存放在記憶體中, 所以不能用取址運算子“ &”來獲取 register 變數的地址。

static:這個關鍵字在 C 語言裡主要有兩個作用。

第一個作用:修飾變數。變數又分為區域性和全域性變數,但它們都存在記憶體的靜態區。

靜態全域性變數,作用域僅限於變數被定義的檔案中,其他檔案即使用 extern 宣告也沒法

使用他。準確地說作用域是從定義之處開始,到檔案結尾處結束,在定義之處前面的那些

程式碼行也不能使用它。想要使用就得在前面再加 extern ***。

靜態區域性變數,在函式體裡面定義的,就只能在這個函式裡用了,同一個文件中的其他

函式也用不了。由於被 static 修飾的變數總是存在記憶體的靜態區,所以即使這個函式執行結束,這個靜態變數的值還是不會被銷燬,函式下次使用時仍然能用到這個值。

 

第二個作用:修飾函式。函式前加 static 使得函式成為靜態函式。函式的作用域僅侷限於本檔案(所以又稱內部函式)。使用內部函式的好處是:不同的人編寫不同的函式時,不用擔心自己定義的函式,是否會與其它檔案中的函式同名。

 

【規則 1-1】命名應當直觀且可以拼讀,可望文知意,便於記憶和閱讀。

【規則 1-2】命名的長度應當符合“min-length && max-information”原則。

【規則 1-3】當識別符號由多個片語成時,每個詞的第一個字母大寫,其餘全部小寫。

【規則 1-4】儘量避免名字中出現數字編號,如 Value1,Value2 等,除非邏輯上的確需要編

號。比如驅動開發時為管腳命名,非編號名字反而不好。

【規則 1-5】對在多個檔案之間共同使用的全域性變數或函式要加範圍限定符(建議使用模組名(縮寫)作為範圍限定符)。

【規則 1-6】識別符號名分為兩部分:規範識別符號字首(字尾) + 含義標識 。非全域性變數可以不用使用範圍限定符字首。

【規則 1-7】作用域字首命名規則。

【規則 1-8】資料型別字首命名規則。

【規則 1-9】含義標識命名規則,變數命名使用名詞性片語,函式命名使用動詞性片語。

【規則 1-10】程式中不得出現僅靠大小寫區分的相似的識別符號。

【規則 1-11】一個函式名禁止被用於其它之處。

【規則 1-12】所有巨集定義、列舉常數、只讀變數全用大寫字母命名,用下劃線分割單詞。

風格這些應與專案中一致,與專案開發成員共同約定並在詳細設計文件中給出

【規則 1-13】考慮到習慣性問題,區域性變數中可採用通用的命名方式,僅限於 n、 i、 j 等作為迴圈變數使用。

【規則 1-14】定義變數的同時千萬千萬別忘了初始化。定義變數時編譯器並不一定清空了

這塊記憶體,它的值可能是無效的資料。

【規則 1-15】不同型別資料之間的運算要注意精度擴充套件問題,一般低精度資料將向高精度

資料擴充套件。

 

sizeof:sizeof 在計算變數所佔空間大小時,括號可以省略,而計算型別(模子)大小時不能省略。

sizeof(int) *p的意思是sizeof(int)的值乘於p

int a[100] sizeof(a) = 400 sizeof(&a) = 400 sizeof(&a[0]) = 4

&a不是指向指標的指標,因為&a和a的值相等,但是*&a和*a的值不相等。*&a和a的值一樣,說明*&a僅僅是對這個陣列指標進行了取值,取得的是陣列的值,即陣列首元素的地址,而不是對&a這個地址進行了取值。這個應該是c語言中針對陣列指標運算的規定。

 

Signed + unsigned = unsigned

 

空指令儘量用NULL;而不是一個分號;要讓人知道這裡不執行如何操作。

 

【規則 1-17】先處理正常情況,再處理異常情況。

在編寫程式碼是,要使得正常情況的執行程式碼清晰,確認那些不常發生的異常情況處理

程式碼不會遮掩正常的執行路徑。這樣對於程式碼的可讀性和效能都很重要。

 

case 後面只能是整型或字元型的常量或常量表示式

【規則 1-21】按字母或數字順序排列各條 case 語句。

【規則 1-22】把正常情況放在前面,而把異常情況放在後面。

【規則 1-23】按執行頻率排列 case 語句

【規則 1-24】簡化每種情況對應的操作。

 

continue語句只用在for、while、do-while等迴圈體中, 常與if條件語句一起使用, 用來加速迴圈。不能應用在switch中。

 

【規則 1-34】如果函式無引數,那麼應宣告其引數為 void 因為有的編譯器無引數可以編譯通過

void *pvid; pvoid++;ANSI錯誤 GNU正確

 

【規則 1-38】 return 語句不可返回指向“棧記憶體”的“指標”,因為該記憶體在函式體結束時被自動銷燬。

 

return; 在ARM裡面返回的r是r0,其它晶片不知道,需要查一下暫存器程式呼叫規則,

int a = return ; 那麼a = r0的值。

 

const: 定義 const 只讀變數,具有不可變性。

case 語句後面是不可以可以是 const 修飾的只讀變數

         節省空間,避免不必要的記憶體分配,同時提高效率,(不分配儲存空間,是一個編譯期間的值)

         const 定義的只讀變數在程式執行過程中只有一份拷貝(因為它是全域性的只讀變數,存放在靜態區),而#define 定義的巨集常量在記憶體中有若干個拷貝。

const int *p; //const 修飾*p,p 是指標, *p 是指標指向的物件,不可變

int const *p; //const 修飾*p,p 是指標, *p 是指標指向的物件,不可變

int *const p; //const 修飾 p, p 不可變, p 指向的物件可變

const int *const p; //前一個 const 修飾*p,後一個 const 修飾 p,指標 p 和 p 指向的物件

都不可變

volatile :const volatile int i= 10;實際上此宣告表示的申明瞭一個const int型的變數,所以i是隻讀變數,不能被修改。同時i又被volatile修飾了,意思就是說不允許編譯器優化程式碼,在程式碼中每次用到i時都要直接從記憶體中去取數。

所以,雖然const volatile int i = 10;定義沒錯,但是這樣的定義沒有什麼實際的意義。

extern int i; //寫成 i = 10;行嗎? 全域性可以,全域性變數預設是extern   區域性不行

extern void fun( void);//兩個 void 可否省略?可以,函式預設是int

int j = 1; extern double j; //這樣行嗎?為什麼? 可以,extern只是宣告

 

struct: 空結構 sizeof為1;

C99 中,結構中的最後一個元素允許是未知大小的陣列,這就叫做柔性陣列成員,但結

構中的柔性陣列成員前面必須至少一個其他成員。柔性陣列成員允許結構中包含一個大小可

變的陣列。sizeof 返回的這種結構大小不包括柔性陣列的記憶體。包含柔性陣列成員的結構用

malloc ()函式進行記憶體的動態分配,並且分配的記憶體應該大於結構的大小,以適應柔性陣列

的預期大小。typedef struct

{

         char c;

         int a[];

}aa; 

sizeof(aa)為4;

 

union大小端模式判斷:

int checkSystem( )

{

union check

{

int i;

char ch;

} c;

c.i = 1;

return (c.ch ==1);

}

 

const Stu_pst stu3; Stu_pst是型別省略,修飾指標。

 

編譯器用空格代替原來的註釋

相關文章