前言:C預處理在程序執行之前查看程序(稱之爲預處理器)。根據程序中的預處理指令,預處理器把符號替換成其表示的內容。本篇主要是爲了寫“大程序結構”作準備,其中包含了宏的說明和基本用法,還有#include"",或#include<>的區別,還有”標準頭文件結構“
一、編譯預處理和宏
1、編譯預處理指令
- #開頭是編譯預處理指令;
- 它們不是C語言的成分,但C語言程序離不開它們
- #define用來定義一個宏
2、宏的說明和基本用法
1)例子:
/* #define <名字> <值> */
#define PI 3.14 //一般名字都用全大寫
- 注意沒有結尾的分號,因爲不是C語句
- 名字必須是一個單詞,值可以是各種東西(等會兒會舉例)
- 在C語言的編譯器開始編譯之前,編譯預處理程序會把程序中的名字替換成值
- 注意:這裏是完全的文本替換
- 如果一個宏的值中有其它宏的名字,也是會被替換的
- 如果一個宏的值超過一行,最後一行之前的行末加‘\‘
- 宏值後面出現的註釋不會被當作宏的一部分
2)沒有值的宏
#define _DEBUG
這類宏是用於條件編譯的,後面有其它的編譯預處理指令來檢查這個宏是否已被定義過了;
3)帶參數的宏的原則
#define SQUAER(x) ((x)(x))//這是一個類宏函數,實現平方的功能
#define MIN(a,b) ((a)>(b)?(a):(b)) //可以帶多個參數
- 一切參數都要括號
- 整個值要括號
- 參數出現的每個地方都要括號
應用場景:
- 在大型程序的代碼中使用非常普遍
- 可以非常複雜,如"產生"函數
二、大程序結構
1、多個源代碼文件
多個.c文件,
- main( )裏的代碼太長了適合分成幾個函數
- 一個源代碼太長了適合分成幾個文件
- 兩個獨立的源代碼文件不能編譯成可執行的程序
2、項目
- 在Dev C++中新建一個項目,然後把幾個源代碼文件加入進去
- 對於項目,Dev C++的編譯會把一個項目中所有的源代碼都編譯後,鏈接起來
- 有的IDE有分開的編譯和構建兩個按鈕,前者是對單個源代碼文件編譯,後者是對整個項目做鏈接
3、編譯單元
- 一個C文件時一個編譯單元
- 編譯器每次只能處理一個編譯單元
4、頭文件(可以看成是一個合同)
- 把函數原型放到一個頭文件(以.h結尾)中,在需要調用這個函數的源代碼文件(.c)中#include(引用)這個頭文件,就能讓編譯器在編譯時知道函數的原型
5、#include“ "、還是#include<>
- #include有兩種形式來指出要插入的文件
- " "要求編譯器首先在當前目錄(.c文件所在的目錄)尋找這個文件,如果沒有,到編譯器指定目錄去找
- < >讓編譯器只能在指定目錄去找
- 編譯器知道自己的標準庫的頭文件在哪裏
- 環境變量和編譯器命令行參數也可以指定尋找頭文件的目錄
6、標準頭文件結構
爲了避免重複聲明結構,例子:
//name.h --修訂後的name_st頭文件,避免重複
#ifndef NAMES_H_
#define NAMES_H_
//多個.c文件共用的宏可以寫在頭文件程序裏
#define SLEN 32
//多個.c文件共用的變量也可以寫在頭文件裏
extern int i;
//結構聲明
struct names_st{
char first[SLEN];
char last[SLEN];
};
//類型定義
typedef struct name_st names;
//函數原型
void get_names(names *);
void show_names(const names *);
char * s_gets(char * st, int n)l
#endif
注:
- 運用條件編譯和宏,保證這個頭文件在編譯單元只能被#include一次;
- #pragma once起同樣效果,但不是所有編譯器都支持;