8種機械鍵盤軸體對比
本人程式員,要買一個寫代碼的鍵盤,請問紅軸和茶軸怎麼選?
宏定義
基本概念預處理部分: #include #define 放在函數之外,一般都放在源文檔的前面
預處理由預處理程序負責,當對一個源文檔進行編譯時,系統将自動引用預處理程序對源程序中的預處理部分作處理,處理完畢将自動進入對源程序的編譯。
C語言提供了多種預處理功能,如宏定義、文檔包含、條件編譯等。
不帶參數的宏定義被定義為 宏 的辨別符稱為 宏名。 在編譯階段對程序中所有出現的 宏名 都用宏定義中的字元串去代換
宏定義由源程序中的宏定義指令完成的。宏代換是由預處理程序自動完成的。
c語言中 宏分為 有參數 和無參數兩種。1
2
3
4
5
6
7#define 辨別符 字元串
以 # 開頭的均為預處理指令
define 為預處理指令
辨別符 為所定義的宏名
字元串 可以是常數、表達式、格式串等
宏使用時的注意事項習慣上宏名用大寫字母表示,以便于與變量差別,但是也允許使用小寫字母
宏定義是用宏名表示一個字元串(可以是任何字元,常數,表達式),在宏展開時又以該字元串取代宏名。
預處理程序不做檢查,在宏展開編譯的時候發現
宏定義不是說明或語句,末尾不用加 分号“;” 加“;” 連同“;”一起置換
宏定義必須寫在函數之外,預設的有效區到源程序結束, 要是提前結束 使用 #undef 指令1
2#undef PI
宏名在源程序中使用雙引号括起來,則預處理程序不對其作宏代換1
2
3
4
5
6
7#define H "hello world"
int main(){
printf(H);
printf("n%sn",H);
printf("Hn"); // H
}
宏定義允許嵌套,在宏展開時由預處理程序層層代換1
2
3#define PI 3.1415926
#define R 5
#define SUM 2*PI*R
可用宏定義表示資料類型,使書寫友善
對輸出格式做宏定義,減少書寫麻煩
#define 和 typedef的差別注意用宏定義表示資料類型和用typedef定義資料說明符的差別。宏定義隻是簡單的字元串代換,是在預處理完成的,而typedef是在編譯時處理的,不是作簡單的代換,而是對類型說明符重新命名,被命名的辨別符具有類型定義說明的功能。1
2
3
4
5
6
7
8
9
10#define PIN1 int *
typedef int * PIN2;
PIN1 a,b
a = &m; // OK int *a; a = &m;
b = &n; // ERROE int b; b = &n;
PIN2 c,d;
c = &m; // OK int *c; c = &m;
d = &n; // OK int *d; d = &n;
帶有參數的宏定義有參宏的定義方法
C語言中允許帶有參數,在宏定義中的參數成為形式參數,在宏調用中的參數稱為實際參數。
對帶參數的宏,在調用中,不僅要宏展開,而且要用實參去代換形參。1
2
3
4
5
6
7
8
9
10
11// 帶參數的宏定義的一般形式為:
#define 宏名(形參表) 字元串
// 帶參宏調用的一般形式為:
宏名(實參表)
eg:
// 宏定義
#define M(y) y*y+3*y
// 宏調用
M(5);
有參宏的注意事項帶參宏定義中,形參之間可以出現空格,但是宏名和形參表之間不能有空格出現。
帶參宏定義中,形參不配置設定記憶體單元,實參有具體值,必須作類型說明,帶參宏定義隻是符号代換,不存在值傳遞。而函數中形參和實參是兩個不同的量,有各自的作用域,調用時進行 值傳遞
在宏定義中形參是辨別符,而宏調用中的實參可以是表達式
在宏定義中,字元串中的形參通常要用括号括起來避免出錯。
宏定義可以用來定義多個語句。在宏調用時,把這些語句又代換到源程序内。
條件編譯
為什麼要用條件編譯?按不同條件去編譯不同的程序部分,因而産生不同的目标代碼文檔。有利于程序的移植和調試。
可以使用條件語句來實作條件編譯。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28// 第一種形式
#if 常量表達式
程序段1
#elif
程序段2
#else
程序段3
#endif
條件編譯後面的表達式中不能出現變量,隻能識别常量和宏定義
// 第二種形式
#ifdef 辨別符
程序段1
#else
程序段2
#elseif
// 如果辨別符已被#define指令定義過則對程序段1進行編譯;否則對程序段2進行編譯。
// 第三種形式
#ifndef 辨別符
程序段1
#else
程序段2
#endif
// 如果辨別符未被 #define 指令定義, 則對程序段1進行編譯,否則對程序段2進行編譯。
預處理
什麼是預處理?以 # 開頭的代碼行
#号必須是該行除了任何空白字元外的第一個字元。
#後是指令關鍵字,在關鍵字和#号之間允許存在任意個數的空白字元。
整行語句構成了一條預處理指令,該指令将在編譯器進行編譯之前對源代碼做某些轉換
常見的預處理指令指令說明#空指令,無任何效果
#include包含一個源代碼文檔
#define定義宏
#undef取消已定義的宏
#if如果給定條件為真,編譯下面的代碼
#ifdef如果宏已經定義,編譯下面的代碼
#ifndef如果宏沒有定義,編譯下面的代碼
#elif#if不為真,目前條件為真,編譯下面的代碼
#endif結束條件編譯塊
static和extern的使用它們都是用來修飾變量(局部的static實際也是全局)
static修飾的變量 隻有你的包含那個變量定義的源代碼文檔可以通路
extern定義的變量 是任何一個源文檔都可以通路,隻要聲明了就可以
static與extern對局部變量的作用static對局部變量的作用延長局部變量的生命周期,從程序啟動到程序退出,但是它沒有改變 變量的 作用域
定義變量的代碼在整個程序運作期間僅僅會執行一次1
2
3
4
5
6
7
8
9
10
11
12
13
14void add(){
static int a = 10; // int a = 10;
a++;
printf("a++: %dn",a);
}
int main() {
add(); // 11
add(); // 12
add(); // 13
return 0;
}
// extern 不是定義局部變量,它是在函數内部聲明的全局變量
static與extern對全局變量的作用全局變量内部變量:隻能在本文檔中通路的變量
外部變量:可以在其他中通路的變量,預設所有全局變量都是外部變量static作用聲明一個内部變量
定義一個内部變量
注意:在不同文檔中可以定義同名的内部變量如果聲明的時候沒有寫extern那系統會自動定義這個變量,并将其初始化為0
如果你使用extern來聲明一個變量,如果沒有你定義的,那麼系統就會報錯
static與extern對函數的作用内部函數: 在A文檔中定義的函數,在A文檔中通路
外部函數: 在B文檔中通路A文檔中定義的函數,函數在B中稱之為外部函數
全局變量&局部變量常見問題
局部變量能否和全局變量重名?能,局部會屏蔽全局,要用全局變量,需要使用”::”(域運算符)
如何引用一個已經定義過的全局變量?extern, 可以用引用頭文檔的方式,也可以用extern關鍵字,使用引入頭文檔方式(有錯誤會在編譯階段報錯),使用extern方式引用時(有錯誤會在連接配接期間報錯)
全局變量可以定義在被多個.c文檔包含的頭文檔中?可以,在不同的C文檔中以static形式來聲明同名全局變量
static全局變量和普通的全局變量差別static全局變量隻初始化一次,防止在其他文檔單元中被引用.
static局部變量和普通的局部變量差別static局部變量隻被初始化一次,下一次依據上一次的結果值.
static函數和普通函數差別static函數在記憶體中隻有一份,普通函數在每個被調用中維持一份拷貝.
程序的局部變量存在于(堆棧)中,全局變量存在于(靜态區)中,動态申請資料存在于(堆)中