1. 程式人生 > >c語言要點筆記

c語言要點筆記



目錄(?)[-]

  1. 資料型別與變數
  2. autostaticregister分析
  3. break和continue的區別
  4. void
  5. void指標的意義
  6. extern
  7. sizeof
  8. const
  9. volatile
  10. 柔性陣列
  11. union和struct的區別
  12. union
  13. enum
  14. 列舉型別和define的區別
  15. typedef
  16. 註釋符號
  17. 接續符
  18. 單引號和雙引號
  19. C語言隱式型別轉換
  20. 巨集定義與使用分析
  21. include
  22. 條件編譯ifelseendif
  23. error用法

*資料型別與變數

1、資料型別可以理解為固定記憶體大小的別名。 2、資料型別是建立變數的模子。 eg,char是1個byte記憶體的別名,short int是2個byte記憶體的別名,int是4個byte記憶體的別名. 3、變數是一段實際連續儲存空間的別名。 程式中通過變數來申請並命名儲存空間,通過變數的名字可以使用儲存空間。

*auto,static,register分析

1、auto是c語言中區域性變數的預設屬性,編譯器預設所有的區域性變數都是auto的。
auto變數儲存在程式的棧中,變數使用時即在棧中分配記憶體,使用後即從棧中釋放變數,不佔用棧空間。 2、static具有“作用域限定符”的意義:①static修飾的全域性變數作用域只是宣告的檔案中;②static修飾的函式作用域只是宣告的檔案中。 static修飾的變數只初始化一次。 static修飾的區域性變數儲存在程式靜態區。 3、register關鍵字指明將變數儲存於暫存器中。 register只是請求暫存器變數,但不一定請求成功。 不能用&運算子獲取register變數的地址。
register變數請求儲存於CPU暫存器中。

*break和continue的區別

1、break表示終止迴圈的執行,跳出塊的操作,white,do...while,for為三種不同型別的迴圈塊,可用break。 2、continue表示終止本次迴圈體,進入下次迴圈執行。

*void

void修飾函式返回值和引數,僅為了表示無: 1、如果函式沒有返回值,應將其宣告為void型。 2、如果函式沒有引數,應宣告其引數為void。

*void指標的意義

1、C語言規定只有相同型別的指標才可以相互賦值。 2、void*指標作為左值用於“接收”任意型別的指標。 3、void*指標作為右值賦值給其它指標時需要強制型別轉換。 eg: int* pi = (int*)malloc(sizeof(int)); char* pc = (char*)malloc(sizeof(char)); void* p = NULL; int* pni = NULL; char* pnc = NULL; p = pi; (正確) pni = p; (錯誤) p = pc; (正確) pnc = p; (錯誤)

*extern

1、extern用於宣告外部定義的變數和函式。 2、extern用於“告訴”編譯器用C方式編譯。C++編譯器和一些變種C編譯器預設會按照“自己”的方式編譯函式和變數,通過extern關鍵字可以命令編譯器“以標準C方式進行編譯”。 eg: extern "C" { int f(int a, intb) { return a+b; } }

*sizeof

1、sizeof是編譯器的內建指示符,不是函式。 2、sizeof用於“計算”相應實體所佔的記憶體大小。 3、sizeof的值在編譯期就已經確定。

*const

1、const修飾變數: 在C語言中const修飾的變數是隻讀的,變數的值放在記憶體的資料表中,每次呼叫時,則直接從資料表中讀取變數的值。const修飾的變數本質還是變數,可以通過指標改變變數的值。 2、const修飾指標: 口訣:左數右指 當const出現在*號左邊時,指標指向的資料為常量。 當const出現在*號右邊時,指標本身為常量。 eg: const int* p; //p可變,p指向的內容不可變 int const* p; //p可變,p指向的內容不可變 int* const p; //p不可變,p指向的內容可變 const int* const p; //p和p指向的內容都不可變 3、const修飾函式和返回值: const修飾函式引數表示在函式體內不希望改變引數的值。 const修飾函式返回值表示返回值不可改變,多用於返回指標的情形。 eg: const int* func() { static int count = 0; count++; return &count; }

*volatile

1、volatile可理解為“編譯器警告指示字”。 2、volatile用於告訴編譯器必須每次去記憶體中取變數值。 3、volatile主要修飾可能被多個執行緒訪問的變數。 4、volatile也可以修飾可能被未知因素更改的變數。

*柔性陣列

1、由結構體產生柔性陣列。 2、柔性陣列即陣列大小待定的陣列。 3、C語言中結構體的最後一個元素可以是大小未知的陣列。 4、C語言中可以由結構體產生柔性陣列。 eg: struct softArray { int len; int array[]; }

*union和struct的區別

1、struct中的每個域在記憶體中都獨立分配空間。 2、union只分配最大的空間,所有域共享這個空間。 eg: struct A { int a; int b; int c; }; union B { int a; int b; int c; }; int main() { printf("%d\n", sizeof(A)); //12位元組 printf("%d\n", sizeof(B)); //4位元組 return 0; }

*union

1、同一個記憶體段可以用來存放幾種不同型別的成員,但在每一個時刻只能存在其中一種,起始地址相同。 2、共用體變數中起作用的成員是最後一個存放的成員,原有的成員被覆蓋。 3、union變數不能作為函式引數。

*enum

1、列舉是一個被命名的整型常數的集合。 2、列舉中每個識別符號的結束符是“,”,不是";",最後 一個成員可省略。不準對列舉變數做++或--。 3、初始化時可以賦負數,以後的識別符號仍依次加1。 4、列舉變數只能取列舉結構中的某個識別符號常量。

*列舉型別和#define的區別

1、#define巨集常量只是簡單的進行值替換,列舉常量是真正意義上的常量。 2、#define巨集常量無法被除錯,列舉常量可以。 3、#define巨集常量無型別資訊,列舉常量是一種特定型別的常量。


*typedef

1、typedef用於給一個已存在的資料型別重新命名,並沒有產生新的型別。 2、typedef重新命名的型別不能進行unsigned 和 signed擴充套件。

*註釋符號

1、編譯器會在編譯過程刪除註釋,但不是簡單的刪除,而是用空格代替。 2、編譯器認為雙引號括起來內容都是字串,雙斜槓也不例外。 3、/*...*/型註釋不能被巢狀。 eg: ①、int/*...*/;         正確 ②、char* s = "abcdefgh //hijklmn"; /正確 ③、//Is it a \ valid comment?             正確 ④、in/*..*/t;         錯誤

*接續符“\"

1、編譯器會將反斜槓剔除,跟在反斜槓後面的字元自動解到前一行。 2、在接續單詞時,反斜槓之後不能有空格,反斜槓的下一行之前也不能有空格。 3、接續符適合在定義巨集程式碼塊時使用。 eg: #define swap(a, b) \ { \ int temp = a; \ a = b; \ b = temp; \ }

*單引號和雙引號

1、C語言中的單引號用來表示字元常量。 2、C語言中的雙引號用來表示字串常量。 3、本質上單引號括起來的一個字元代表整數。 4、雙引號括起來的字元代表一個指標。 5、C編譯器接受字元和字串的比較,可意義是錯誤的。 6、C編譯器允許字串對字元變數賦值,其意義是可笑的。 eg: 'a'表示字元常量,在記憶體中佔1個位元組。 'a'+1表示‘a'的ASCII碼加1,結果為’b'。
“a"表示字串常量,在記憶體中佔2個位元組。 “a"+1表示指標運算,結果指向”a"結束符‘\0’。

*C語言隱式型別轉換

1、算術運算式中,低型別轉換為高型別。 2、賦值表示式中,表示式的值轉換為左邊變數的型別。 3、函式呼叫時,實參轉換為形參的型別。 4、函式返回值,return表示式轉換為返回值型別。 char->short->int->unsigned int->long->unsigned long->double float

*巨集定義與使用分析

1、巨集定義常量 ①、#define定義巨集常量可以出現在程式碼的任何地方。 ②、#define從本行開始,之後的程式碼都可以使用這個巨集常量。 eg: #define ERROR -1 正確 #define PI 3.141592653 正確 #define PATH_1 "D:\Delph:\C\Topic3.ppt" 正確 #define PATH_2 D:\Delph:\C\Topic3.ppt 正確 #define PATH_3 D:\Delph:\C\ Topic3.ppt 正確
2、巨集定義表示式 ①、#define表示式給有函式呼叫的假象,卻不是函式。 ②、#define表示式可以比函式更強大。 ③、#define表示式比函式更容易出錯。 eg: #define SUM(a, b) (a)+(b) #define MIN(a, b) ((a)<(b) ? (a):(b)) #define DIM(a) (sizeof(a) / sizeof(*a))
3、巨集表示式與函式的對比 1、巨集表示式在預編譯期被處理,編譯器不知道巨集表示式的存在。 2、巨集表示式用“實參”(資料型別、常量、變數)完全代替形參,不進行任何運算。 3、巨集表示式沒有任何的“呼叫”開銷。 4、巨集表示式不能出現遞迴定義。 eg: #define FAC(n) ((n>0)?(FAC(n-1)+1):0) int j = FAC(100); (錯誤) 5、巨集定義的常量或表示式沒有作用域限制,除非用#undef來限制作用域。 eg: int f1(int a, int b) { #define MIN(a, b) ((a)<(b) ? a:b) return MIN(a,b) //MIN表示式只在f1中有用 #undef MIN } int f2(int a, int b, int c) { return MIN(MIN(a, b), c) //出錯,不能使用MIN }

*#include

1、#include 本質是將已經存在的檔案內容嵌入到當前檔案中。 2、#include的間接包含同樣會產生嵌入檔案內容的動作。 3、為避免檔案的重複包含,可用以下結構在.h檔案中,則標頭檔案可以任意包含。 #ifndef _FILE_H_ #define _FILE_H_ .. #endif

*條件編譯:#if...#else...#endif

1、條件編譯是預編譯指示指令,用於控制是否編譯某段程式碼。 2、條件編譯使得我們可以按不同的條件編譯不同的程式碼段,因而可以產生不同的目的碼。 3、#if...#else...#endif被預編譯器處理; if...else語句被編譯器處理,必然被編譯進目的碼。 4、實際工程中條件編譯主要用於以下兩種情況: 不同的產品線共用一份程式碼。 區分編譯產品的除錯版和釋出版。

*#error用法

#error用於生成一個編譯錯誤訊息,並停止編譯。 用法:#error message 注:message不需要用雙引號包圍 #error編譯指示字用於自定義程式設計師特有的編譯錯誤訊息。 #warning用於生成編譯警告,但不會停止編譯。

目錄(?)[-]

  1. 資料型別與變數
  2. autostaticregister分析
  3. break和continue的區別
  4. void
  5. void指標的意義
  6. extern
  7. sizeof
  8. const
  9. volatile
  10. 柔性陣列
  11. union和struct的區別
  12. union
  13. enum
  14. 列舉型別和define的區別
  15. typedef
  16. 註釋符號
  17. 接續符
  18. 單引號和雙引號
  19. C語言隱式型別轉換
  20. 巨集定義與使用分析
  21. include
  22. 條件編譯ifelseendif
  23. error用法

*資料型別與變數

1、資料型別可以理解為固定記憶體大小的別名。 2、資料型別是建立變數的模子。 eg,char是1個byte記憶體的別名,short int是2個byte記憶體的別名,int是4個byte記憶體的別名. 3、變數是一段實際連續儲存空間的別名。 程式中通過變數來申請並命名儲存空間,通過變數的名字可以使用儲存空間。

*auto,static,register分析

1、auto是c語言中區域性變數的預設屬性,編譯器預設所有的區域性變數都是auto的。 auto變數儲存在程式的棧中,變數使用時即在棧中分配記憶體,使用後即從棧中釋放變數,不佔用棧空間。 2、static具有“作用域限定符”的意義:①static修飾的全域性變數作用域只是宣告的檔案中;②static修飾的函式作用域只是宣告的檔案中。 static修飾的變數只初始化一次。 static修飾的區域性變數儲存在程式靜態區。 3、register關鍵字指明將變數儲存於暫存器中。 register只是請求暫存器變數,但不一定請求成功。 不能用&運算子獲取register變數的地址。 register變數請求儲存於CPU暫存器中。

*break和continue的區別

1、break表示終止迴圈的執行,跳出塊的操作,white,do...while,for為三種不同型別的迴圈塊,可用break。 2、continue表示終止本次迴圈體,進入下次迴圈執行。

*void

void修飾函式返回值和引數,僅為了表示無: 1、如果函式沒有返回值,應將其宣告為void型。 2、如果函式沒有引數,應宣告其引數為void。

*void指標的意義

1、C語言規定只有相同型別的指標才可以相互賦值。 2、void*指標作為左值用於“接收”任意型別的指標。 3、void*指標作為右值賦值給其它指標時需要強制型別轉換。 eg: int* pi = (int*)malloc(sizeof(int)); char* pc = (char*)malloc(sizeof(char)); void* p = NULL; int* pni = NULL; char* pnc = NULL; p = pi; (正確) pni = p; (錯誤) p = pc; (正確) pnc = p; (錯誤)

*extern

1、extern用於宣告外部定義的變數和函式。 2、extern用於“告訴”編譯器用C方式編譯。C++編譯器和一些變種C編譯器預設會按照“自己”的方式編譯函式和變數,通過extern關鍵字可以命令編譯器“以標準C方式進行編譯”。 eg: extern "C" { int f(int a, intb) { return a+b; } }

*sizeof

1、sizeof是編譯器的內建指示符,不是函式。 2、sizeof用於“計算”相應實體所佔的記憶體大小。 3、sizeof的值在編譯期就已經確定。

*const

1、const修飾變數: 在C語言中const修飾的變數是隻讀的,變數的值放在記憶體的資料表中,每次呼叫時,則直接從資料表中讀取變數的值。const修飾的變數本質還是變數,可以通過指標改變變數的值。 2、const修飾指標: 口訣:左數右指 當const出現在*號左邊時,指標指向的資料為常量。 當const出現在*號右邊時,指標本身為常量。 eg: const int* p; //p可變,p指向的內容不可變 int const* p; //p可變,p指向的內容不可變 int* const p; //p不可變,p指向的內容可變 const int* const p; //p和p指向的內容都不可變 3、const修飾函式和返回值: const修飾函式引數表示在函式體內不希望改變引數的值。 const修飾函式返回值表示返回值不可改變,多用於返回指標的情形。 eg: const int* func() { static int count = 0; count++; return &count; }

*volatile

1、volatile可理解為“編譯器警告指示字”。 2、volatile用於告訴編譯器必須每次去記憶體中取變數值。 3、volatile主要修飾可能被多個執行緒訪問的變數。 4、volatile也可以修飾可能被未知因素更改的變數。

*柔性陣列

1、由結構體產生柔性陣列。 2、柔性陣列即陣列大小待定的陣列。 3、C語言中結構體的最後一個元素可以是大小未知的陣列。 4、C語言中可以由結構體產生柔性陣列。 eg: struct softArray { int len; int array[]; }

*union和struct的區別

1、struct中的每個域在記憶體中都獨立分配空間。 2、union只分配最大的空間,所有域共享這個空間。 eg: struct A { int a; int b; int c; }; union B { int a; int b; int c; }; int main() { printf("%d\n", sizeof(A)); //12位元組 printf("%d\n", sizeof(B)); //4位元組 return 0; }

*union

1、同一個記憶體段可以用來存放幾種不同型別的成員,但在每一個時刻只能存在其中一種,起始地址相同。 2、共用體變數中起作用的成員是最後一個存放的成員,原有的成員被覆蓋。 3、union變數不能作為函式引數。

*enum

1、列舉是一個被命名的整型常數的集合。 2、列舉中每個識別符號的結束符是“,”,不是";",最後 一個成員可省略。不準對列舉變數做++或--。 3、初始化時可以賦負數,以後的識別符號仍依次加1。 4、列舉變數只能取列舉結構中的某個識別符號常量。

*列舉型別和#define的區別

1、#define巨集常量只是簡單的進行值替換,列舉常量是真正意義上的常量。 2、#define巨集常量無法被除錯,列舉常量可以。 3、#define巨集常量無型別資訊,列舉常量是一種特定型別的常量。


*typedef

1、typedef用於給一個已存在的資料型別重新命名,並沒有產生新的型別。 2、typedef重新命名的型別不能進行unsigned 和 signed擴充套件。

*註釋符號

1、編譯器會在編譯過程刪除註釋,但不是簡單的刪除,而是用空格代替。 2、編譯器認為雙引號括起來內容都是字串,雙斜槓也不例外。 3、/*...*/型註釋不能被巢狀。 eg: ①、int/*...*/;         正確 ②、char* s = "abcdefgh //hijklmn"; /正確 ③、//Is it a \ valid comment?             正確 ④、in/*..*/t;         錯誤

*接續符“\"

1、編譯器會將反斜槓剔除,跟在反斜槓後面的字元自動解到前一行。 2、在接續單詞時,反斜槓之後不能有空格,反斜槓的下一行之前也不能有空格。 3、接續符適合在定義巨集程式碼塊時使用。 eg: #define swap(a, b) \ { \ int temp = a; \ a = b; \ b = temp; \ }

*單引號和雙引號

1、C語言中的單引號用來表示字元常量。 2、C語言中的雙引號用來表示字串常量。 3、本質上單引號括起來的一個字元代表整數。 4、雙引號括起來的字元代表一個指標。 5、C編譯器接受字元和字串的比較,可意義是錯誤的。 6、C編譯器允許字串對字元變數賦值,其意義是可笑的。 eg: 'a'表示字元常量,在記憶體中佔1個位元組。 'a'+1表示‘a'的ASCII碼加1,結果為’b'。
“a"表示字串常量,在記憶體中佔2個位元組。 “a"+1表示指標運算,結果指向”a"結束符‘\0’。

*C語言隱式型別轉換

1、算術運算式中,低型別轉換為高型別。 2、賦值表示式中,表示式的值轉換為左邊變數的型別。 3、函式呼叫時,實參轉換為形參的型別。 4、函式返回值,return表示式轉換為返回值型別。 char->short->int->unsigned int->long->unsigned long->double float

*巨集定義與使用分析

1、巨集定義常量 ①、#define定義巨集常量可以出現在程式碼的任何地方。 ②、#define從本行開始,之後的程式碼都可以使用這個巨集常量。 eg: #define ERROR -1 正確 #define PI 3.141592653 正確 #define PATH_1 "D:\Delph:\C\Topic3.ppt" 正確 #define PATH_2 D:\Delph:\C\Topic3.ppt 正確 #define PATH_3 D:\Delph:\C\ Topic3.ppt 正確
2、巨集定義表示式 ①、#define表示式給有函式呼叫的假象,卻不是函式。 ②、#define表示式可以比函式更強大。 ③、#define表示式比函式更容易出錯。 eg: #define SUM(a, b) (a)+(b) #define MIN(a, b) ((a)<(b) ? (a):(b)) #define DIM(a) (sizeof(a) / sizeof(*a))
3、巨集表示式與函式的對比 1、巨集表示式在預編譯期被處理,編譯器不知道巨集表示式的存在。 2、巨集表示式用“實參”(資料型別