c語言的標頭檔案、巨集、指標
#include命令
#include
是檔案包含命令,主要用來引入對應的標頭檔案。#include
的處理過程很簡單,就是將標頭檔案的內容插入到該命令所在的位置,從而把標頭檔案和當前原始檔連線成一個原始檔,這與複製貼上的效果相同。
#include有兩種使用方式:
#include <stdio.h> #include "myHeader.h"
使用尖括號< >
和雙引號" "
的區別在於標頭檔案的搜尋路徑不同:包含標準庫的標頭檔案建議用尖括號,包含自定義的標頭檔案建議用雙引號。
- 一個#include命令只能包含一個頭檔案,多個頭檔案需要多個#include命令。
- 檔案包含允許巢狀,也就是說在一個被包含的檔案中又可以包含另一個檔案。
巨集定義
#define 巨集名 字元序列
#
表示這是一條預處理命令,所有的預處理命令都以#開頭。define
是預處理命令。巨集名
是識別符號的一種,命名規則和識別符號相同。字元序列
可以是常數、表示式等。
巨集定義的幾點說明
- 巨集定義是用巨集名來表示一個字串,在巨集展開時又以該字串取代巨集名,這只是一種簡單的替換。字串中可以含任何字元,可以是常數,也可以是表示式,預處理程式對它不作任何檢查,如有錯誤,只能在編譯已被巨集展開後的源程式時發現。
- 巨集定義不是說明或語句,在行末不必加分號,如加上分號則連分號也一起替換。
- 巨集定義必須寫在函式之外,其作用域為巨集定義命令起到源程式結束。如要終止其作用域可使用
#undef
命令。#define A 123 #undef A A只在從定義到undef之間有效
巨集定義表示資料型別和用typedef定義資料說明符的區別。
巨集定義只是簡單的字串代換,是在預處理完成的,而typedef是在編譯時處理的,它不是作簡單的代換,而是對型別說明符重新命名。被命名的識別符號具有型別定義說明的功能。
#define PIN1 int * typedef int *PIN2; //也可以寫作typedef int (*PIN2);
從形式上看這兩者相似, 但在實際使用中卻不相同。
下面用PIN1,PIN2說明變數時就可以看出它們的區別:
PIN1 a,b;
在巨集代換後變成:
int *a,b;
表示a是指向整型的指標變數,而b是整型變數。然而:
PIN2 a,b;
表示a、b都是指向整型的指標變數。因為PIN2是一個型別說明符。
由這個例子可見,巨集定義雖然也可表示資料型別, 但畢竟是作字元代換。在使用時要分外小心,以避出錯。http://c.biancheng.net/cpp/html/65.html
int a = 100; a 是一個變數,用來存放整數,需要在前面加&
來獲得它的地址;
char str[20] = "abcdefg"; str 本身就表示字串的首地址,不需要加&
。
printf("%#X, %#X\n", &a, str); %#X
表示以十六進位制形式輸出,並附帶字首0X
。
定義指標變數
定義指標變數與定義普通變數非常類似,不過要在變數名前面加星號*
,格式為:
datatype *name; 或者 datatype *name = value;
*
表示這是一個指標變數,datatype
表示該指標變數所指向的資料的型別 。例如:
int *p1;
p1 是一個指向 int 型別資料的指標變數,至於 p1 究竟指向哪一份資料,應該由賦予它的值決定。再如:
int a = 100;
int *p_a = &a;
在定義指標變數 p_a 的同時對它進行初始化,並將變數 a 的地址賦予它,此時 p_a 就指向了 a。值得注意的是,p_a 需要的一個地址,a 前面必須要加取地址符&
,否則是不對的。
1 //定義普通變數 2 float a = 99.5, b = 10.6; 3 char c = '@', d = '#'; 4 //定義指標變數 5 float *p1 = &a; 6 char *p2 = &c; 7 //修改指標變數的值 8 p1 = &b; 9 p2 = &d;
*
是一個特殊符號,表明一個變數是指標變數,定義 p1、p2 時必須帶*
。而給 p1、p2 賦值時,因為已經知道了它是一個指標變數,就沒必要多此一舉再帶上*
,後邊可以像使用普通變數一樣來使用指標變數。
也就是說,定義指標變數時必須帶*
,給指標變數賦值時不能帶*
。
指標變數也可以連續定義,如:int *a, *b, *c; //a、b、c 的型別都是 int*。
每個變數前面都要帶*
。如果寫成int *a, b, c;,那麼只有 a 是指標變數,b、c 都是型別為 int 的普通變數。
定義指標變數時的*
和使用指標變數時的*
意義完全不同。以下面的語句為例:
- int *p = &a;
- *p = 100;
第1行程式碼中*
用來指明 p 是一個指標變數,第2行程式碼中*
用來獲取指標指向的資料。
需要注意的是,給指標變數本身賦值時不能加*
。修改上面的語句:
- int *p;
- p = &a;
- *p = 100;
第2行程式碼中的 p 前面就不能加*
。
關於 * 和 & 的謎題
假設有一個 int 型別的變數 a,pa 是指向它的指標,那麼*&a
和&*pa
分別是什麼意思呢?*&a
可以理解為*(&a)
,&a
表示取變數 a 的地址(等價於 pa),*(&a)
表示取這個地址上的資料(等價於 *pa),繞來繞去,又回到了原點,*&a
仍然等價於 a。&*pa
可以理解為&(*pa)
,*pa
表示取得 pa 指向的資料(等價於 a),&(*pa)
表示資料的地址(等價於 &a),所以&*pa
等價於 pa。
對星號*
的總結
在我們目前所學到的語法中,星號*
主要有三種用途:
- 表示乘法,例如
int a = 3, b = 5, c; c = a * b;
,這是最容易理解的。 - 表示定義一個指標變數,以和普通變數區分開,例如
int a = 100; int *p = &a;
。 - 表示獲取指標指向的資料,是一種間接操作,例如
int a, b, *p = &a; *p = 100; b = *p;
。
int aa = 97;
int bb = 98;
int *paa = &aa;
printf("%c\n",*paa);
*paa = 99;
printf("%c\n",paa);
paa = bb;
printf("%c\n",paa);
執行結果 a c b