C語言學習——編譯預處理和宏、及標準頭文件結構

前言: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起同樣效果,但不是所有編譯器都支持;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章