條件編譯
條件編譯可以在編譯的時候從幾組語句中選擇一組編譯而忽略其他組,
#ifdef/#ifndef...
#else...
#endif
這個結構可以根據一個宏名稱是否被定義過從兩組語句中選擇一組編譯,最開始的預處理指令都應該從兩個裡選擇一個,不論選擇哪一個都應該在後面寫一個宏名稱。如果最開始的預處理指令選擇#ifdef就表示後面的宏名稱被定義的時候編譯前一組語句否則編譯後一組語句,如果最開始的預處理指令選擇#ifndef效果和#ifdef剛好相反。
練習:編寫點菜程式,要求能編譯成兩個不同的版本
1.代表龍蝦
2.代表小雞燉蘑菇
(有、沒有、真沒有)
/*
*
*點菜程式
*
* */
#include<stdio.h>
int main (){
int order = 0;
printf("請點菜:");
scanf("%d",&order);
#ifdef ZHAOBENSHAN
if (order == 2){
printf("真沒有\n");
}
else {
printf("沒有\n");
}
#else
if (order == 2){
printf("沒有\n");
}
else {
printf("有\n");
}
#endif
return 0;
}
#if...
#elif(任意多次)...
#else...
#endif
以上結構可以實現條件編譯的效果,它可以根據任意邏輯表示式從多組語句中選擇一組編譯。
if和#elif後都需要寫邏輯表示式,這些邏輯表示式裡可以使用任意邏輯運算子,這些邏輯表示式的作用和if分支裡邏輯表示式的作用一樣。
多檔案程式設計
多檔案程式設計的時候任何一個函式只能屬於一個檔案,一個檔案裡可以包含多個函式,多檔案程式設計基本步驟:
1.把所有函式分散在多個不同的原始檔裡(主函式通常單獨佔一個檔案)。
2.為每個原始檔編寫配對的以.h作為擴充名的標頭檔案(主函式所在的原始檔不需要配對的標頭檔案)只要不分配記憶體的內容都可以寫在標頭檔案裡,標頭檔案裡至少應該包含配對原始檔裡的所有函式宣告。
3.修改所有原始檔,在原始檔裡使用#include預處理指令包含必要的標頭檔案(配對標頭檔案是必要標頭檔案,如果原始檔裡使用了某個標頭檔案裡宣告的函式則這個標頭檔案也是必要標頭檔案)。
編譯多檔案程式的時候需要在gcc命令後列出所有原始檔的路徑。
Makefile
可以把多檔案程式的編譯過程記錄在Makefile檔案裡,然後使用make工具根據Makefile檔案的內容進行編譯。
Makefile裡每個編譯命令前都應該用tab鍵而不是空格鍵。
標頭檔案內容如果應該被包含在條件編譯預處理指令中間,這樣可以避免編譯的時候哦反覆多次重複編譯同一個標頭檔案的內容。第一個預處理指令必須是#ifndef,標頭檔案使用的宏名稱應該根據檔名稱變化得到。
Makefile簡單書寫如下,
a.out : main.o func.o
gcc main.o func.o
main.o : main.c
gcc -c main.c
func.c : func.c
gcc -c func.c
練習:編寫函式從鍵盤得到一個整數並把這個整數傳遞給呼叫函式,用多檔案程式設計實現。
/*主函式*/
#include<stdio.h>
#include "11add.h"
int main (){
int num = 0,num1 = 0;
printf("請輸入兩個數字:");
scanf("%d%d",&num,&num1);
printf("%d\n",add(num,num1));
return 0;
}
/*加法函式*/
#include"11add.h"
int add (int num ,int num1){
return num + num1;
}
/*加法函式標頭檔案*/
#ifndef _ADD_H_
#define _ADD_H_
int add(int,int);
#endif //_ADD_H_
全域性變數補充
如果希望從一個原始檔裡使用另外一個原始檔裡宣告的全域性變數就需要使用extern關鍵字再次宣告這個全域性變數,這種使用extern關鍵字宣告的語句不會分配記憶體,他們通常寫在標頭檔案裡。不可以跨檔案使用靜態全域性變數。
結構體
C語言裡可以在一個儲存區裡記錄多個數字,這種儲存區的型別叫結構體型別;這種型別需要建立出來後才能使用,結構體型別的儲存區裡包含多個子儲存區,每個子儲存區可以用來存放一個數字,結構體的不同子儲存區也可以是結構體型別的儲存區。
結構體宣告語句可以用來建立結構體型別,宣告結構體型別的時候需要使用struct關鍵字。結構體宣告語句裡包含多個變數宣告語句,這些變數叫做結構體的成員變數,每個成員變數代表一個子儲存區。成員變數的宣告語句不會分配記憶體,它們只是用來表示子儲存區的型別名稱(成員變數不可以初始化),C語言裡結構體不可以包含函式,結構體宣告語句可以寫在任何地方,包括標頭檔案裡。
可以把結構體作為型別宣告變數,這種變數叫做結構體變數。把結構體作為型別的時候需要把struct關鍵字和結構體名稱一起作為型別名稱使用。結構體變數分配了記憶體,他們可以用來記錄數字。
typedef
typedef關鍵字可以用來給一個資料型別起別名,別名可以用來代替原有的型別名稱,通常會給結構體型別起別名,可以把宣告結構體的語句和起別名的語句合併成一條語句。這個時候可以省略結構體本省的名稱。
宣告結構體變數的時候也應該進行初始化,結構體變數初始化的方法和陣列的初始化方法一樣,結構體變數通常不能作為整體使用,一般一次只是用其中某個子儲存區。以下寫法可以用來表示結構體的某個子儲存區。
/*
*
*結構體
*
* */
#include<stdio.h>
/*struct person{
int age;
float height;
char name[10];
};
typedef struct person sperson;*/
typedef struct /*person*/{
int age;
float height;
char name[10];
}sperson;
int main (){
//struct person prsn; //結構體變數宣告語句
//sperson prsn1 = {18,48.3f,"abc"};
printf("年齡是:%d\n",prsn1.age);
printf("身高是:%g\n",prsn1.height);
printf("名字是:%s\n",prsn1.name);
return 0;
}
prsn.age
其中prsn是結構體變數名稱,age是某個成員變數的名稱。同型別結構體變數之間可以直接賦值,結構體指標用來記錄結構體儲存區的地址,以下寫法可以透過結構體指標表示結構體的子儲存區
p_person- >age
其中p_person是結構體指標,age是成員變數名稱 。