預處理指令

預處理命令

1 . 基本介紹

  • 使用庫函數以前,應該用#include引入對應的頭文件,這種以#開頭的命令稱爲預處理命令
  • 這些在編譯以前對源文件進行簡單加工的過程,就稱爲預處理(即預先處理,提早處理)
  • 預處理主要是處理以#開頭的命令。例如#include<stdio.h>,預處理命令要放在全部函數以外,並且通常都放在源文件的前面
  • 預處理是C語言的一個重要功能,由預處理程序完成,當對一個源文件進行編譯時,系統將自動調用預處理程序對源程序中的預處理部分作處理,處理完畢自動進入對源程序的編譯
  • C語言提供了多種預處理功能,如宏定義,文件包含,條件編譯,合理的使用會使編寫的程序便於閱讀,修改,移植和調試,也有利於程序模塊化設計

2 . 快速入門

2.1 具體要求

  • 開發一個C語言程序,讓它暫停5秒之後再輸出內容「hello 尚硅谷」,而且要求跨平臺,在Windows和Linux下都能運行

2.2 提示

  • Windows平臺下的暫停函數的原型是void Sleep(DWORD dwMilliseconds),參數的單位是「毫秒」,位於<windows.h>頭文件
  • linux平臺下暫停函數的原型是unsigned int sleep(unsigned int second),參數的單位是「秒」,位於<unistd.h>頭文件
  • if ,#endif ,就是預處理命令,他們都是在編譯以前由預處理程序來執行的

2.3 代碼實現

#include<stdio.h>

//說明:在Windows操做系統和Linux操做系統下,生成源碼不同

#incLude<windows.h>

int main(){
    Sleep(5000);
    puts("hello ,尚硅谷");
    getchar();
    rerurn 0;
}

#if_WIN32  //若是是windows平臺,就執行#include<windows.h>
#include<windows.h>
#elif_linux_//不然判斷是否是linux,若是是linux就引入<unistd.h>
#include<unistd.h>
#endif
int main(){
    //不一樣的平臺調用不一樣的函數
    #if_WIN32
    Sleep(5000);
    #elif_linux_
    sleep(5);
    #endif
    puts("hello,尚硅谷");
    getchar();
    return 0;
}

3 . 宏定義

3.1 基本介紹

  • define叫作宏定義命令,它又是C語言預處理命令的一種。所謂宏定義,就是用一個標識符來表示一個字符串,若是在後面的代碼中出現了該標識符,那麼就所有替換成指定的字符串

  • 宏定義在常量有過說明
#define N 100
int main(){
    int sum = 20 + N;
    printf("%d",sum);
    getchar();
    return 0;
}
//說明
//#define N 100就是宏定義,N爲宏名,100是宏的內容(宏所表示的字符串),在預處理階段,對程序中全部出現的宏名,預處理器都會用宏定義中的字符串去代換,這稱爲宏替換或宏展開
//宏定義是由源程序中的宏定義命令#define完成的,宏替換啊是由預處理程序完成的

4 . 宏定義的形式

4.1 #define 宏名 字符串

  • 表示這是一條預處理命令,全部的預處理命令都以#開頭,宏名是標識符的一種,命名規則和變量相同,字符串能夠是數字,表達式,if語句,函數

  • 這裏所說的字符串是通常意義上的字符序列,不要和C語言中的字符串等同,它不須要雙引號
  • 程序中反覆使用的表達式就可使用宏定義

4.2 宏定義#define應用案例

#include <stdio.h>
//宏定義,宏名 M ,對應的字符串(n*n+3*n)
//注意:若是宏對應的字符串有(),那麼就不能省略

#define M (n*n+3*n)
int main(){
    int sum,n;
    printf("Input a number:");
    scanf("%d",&n);
    sum = 3*M+4*M+5*M;
    printf("sum=%d",sum);
    getchar();
    getchar();
    return 0;
}

4.3 宏定義注意事項和細節

  • 宏定義是用宏名來表示一個字符串,在宏展開時又以該字符串取代宏名,這只是一種簡單的替換,字符串中能夠含任何字符,它能夠是常數,表達式,if語句,函數等,預處理程序對它不做任何檢查,只能在編譯已被宏展開後的源程序時發現
  • 宏定義不是說明或語句,在行末沒必要加分號,如價紹加上分號則連分號一塊兒替換
  • 宏定義必須寫在函數以外,其做用域爲宏定義命令起到源程序結束,如要終止其做用域可以使用#undef命令
#define PI 3.14159
int main(){
    printf("PI=%f",PI);
    return 0;
}

#undef PI //取消宏定義
void func(){
    printf("PI=%f",PI);
  • 代碼中的宏名若是被引號包圍,那麼預處理程序不對其做宏替換
#include<stdio.h>
#define OK 100
int main(){
    printf("OK");
    return 0;
}
  • 宏定義容許嵌套,在宏定義的字符串中可使用已經定義的宏名,在宏展開時由預處理程序層層代換
#define  PI 3.1415926
#define S PI*y*y
printf("%s",S);
//在宏替換後變爲
printf("%f",3.1415926*y*y);
  • 習慣上宏名用大寫字母表示,以便於與變量區別,但也容許小寫字母
  • 可用宏定義表示數據類型,使書寫方便
#define UINT unsigned int
void main(){
    UINT a,b;
}
  • 宏定義表示數據類型和用typedef定義數聽說明符的區別:宏定義只是簡單的字符串替換,由預處理器來處理;而typedef是在編譯階段由編譯器處理的,它並非簡單的字符串替換,而給原有的數據類型起一個新的名字,將它做爲一種新的數據類型

5 . 帶參數的宏定義

5.1 基本介紹

  • C語言容許宏帶有參數,在宏定義中的參數稱爲「形式參數」,在宏調用中的參數稱爲「實際參數」,這點和函數有些相似
  • 對帶參數的宏,在展開過程當中不只要進行字符串替換,還要用實參去替代形參
  • 帶參宏定義的通常形式爲#define 宏名 (形參列表)字符串,在字符串中能夠含有各個形參
  • 帶參宏調用的通常形式爲:宏名(實參列表);
#include <stdio.h>

//說明
//1.MAX 就是帶參數的宏
//2.(a,b)就是形參
//3.(a>b)?a:b是帶參數的宏對應字符串,該字符串可使用形參

#define MAX(a,b)?a:b

int main(){
    int x,y,max;
    printf("input two numbers:");
    scanf("%d %d",&x,&y);
    
    //說明
    //1.MAX(x,y);調用帶參宏定義
    //2.在宏替換時(預處理,由預處理器),會進行字符串的替換,同時會使用實參,去替換形參
    //3.即MAX(x,y)宏替換後(x>y)?x:y
    max=MAX(x,y);
    printf("max=%d",max);
    getchar();
    getcahr();
    return 0;
}

5.2 帶參宏定義的注意事項和細節

  • 帶參宏定義中,形參之間能夠出現空格,可是宏名和形參列表之間不能有空格出現
#define MAX(a,b)(a>b)?a:b  //若是寫成了#define MAX (a,b)(
a>b)?a:b
    //將被認爲是無參宏定義,宏名MAX表明字符串(a,b)(a>b)?a:b
    //而不是:MAX(a,b) 表明(a:b)?a:b了

)
  • 在帶參宏定義中,不會爲形式參數分配內存,所以沒必要指明數據類型。而在宏定義中,實參包含了具體的數據,要用他們去替換形參,所以實參必需要指明數據類型
  • 在宏定義中,字符串內的形參一般要用括號括起來以免出錯
#include <stdlib.h>

#define SQ(y)(y)*(y)//帶參宏定義,字符串內的形參一般要用括號括起來以免出錯
int main(){
    int a,sq;
    printf("input a number:");
    scanf("%d",&a);
    sq=SQ(a+1);
    printf("sq=%d",sq);
    system("pause");
    return 0;
}

6 . 帶參宏定義和函數的區別

  • 宏展開僅僅是字符串的替換,不會對錶達式進行計算;宏在編譯以前就被處理掉了,它沒有機會參與編譯,也不要會佔用內存
  • 函數是一段能夠重複使用的代碼,會被編譯,會給它分配內存,每次調用函數,就是執行這塊內存中的代碼
//使用函數計算平均值,使用宏計算平均值,並總結兩者的區別
#include<stdio.h>
#include<stdlib.h>

int SQ(int y){
    return ((y)*(y));
}
int main(){
    int i = 1;
    while(i<=5){
        printf("%d^2=%d",(i-1),SQ(i++));
    }
    system("pause");
    return 0;
}
#include<stdlib.h>
#define SQ(y)((y)*(y))

int main(){
    int i=1;
    while(i<=5){
        printf("%d^2=%d",i,SQ(i++));
    }
    system("pause");
    return 0;
}

7 . C語言預處理命令總結

預處理指令是以#號開頭的代碼行,#號必須是該行除了任何空白字符外的第一個字符。#號後是指令關鍵字,在關鍵字和#號之間容許存在任意個數的空白字符,整行語句構成了一條預處理指令,該指令將在編譯器進行編譯以前對源代碼作某些轉換linux

7.1 常見的預處理指令

指令 說明
# 空指令,無任何效果
#include 包含一個源代碼文件
#define 定義宏
#undef 取消已定義的宏
#if 若是給定條件爲真,則編譯下面代碼
#ifdef 若是宏已經定義,則編譯下面代碼
#ifndef 若是宏沒有定義,則編譯下面代碼
#elif 若是前面的#if給定條件不爲真,當前條件爲真,則編譯下面代碼
#endif 結束一個#if...#else條件編譯塊

8 . 注意事項

  • 預處理功能是C語言特有的功能,他是在對源程序正式編譯前由預處理程序完成的,程序員在程序中用預處理命令來調用這些功能
  • 宏定義能夠帶有參數,宏調用是是以實參換形參,而不是值傳遞
  • 爲了不宏代換時發生錯誤,宏定義中的字符串應加括號,字符串中出現的形式參數兩邊也應加括號
  • 文件包含時預處理 的一個主要功能,它可 用來把多個源文件鏈接成一個源文件進行編譯,結果將生成一個目標文件
  • 條件編譯容許只編譯源程序中知足條件的程序段,使生成的目標程序較短,從而減小了內存的開銷並提升了程序的效率
  • 使用預處理功能便於程序的修改,閱讀,移植和調試,也便於實現模塊化程序設計。
相關文章
相關標籤/搜索