天天看點

黑馬程式員——C語言知識點總結之預處理指令和typedef關鍵字預處理指令關鍵字typedef

——Java教育訓練、Android教育訓練、iOS教育訓練、.Net教育訓練、期待與您交流!——

預處理指令

1、C語言在對源程式進行編譯之前,會先對一些特殊的預處理指令作解釋(比如之前使用的#include檔案包含指令),産生一個新的源程式(這個過程稱為編譯預處理),之後再進行通常的編譯

2、為了區分預處理指令和一般的C語句,所有預處理指令都以符号”#”開頭,并且結尾不用分号

3、宏名一般用大寫或者以k開頭,變量名一般用小寫

4、C語言提供的預處理指令主要有:宏定義、檔案包含、條件編譯

宏定義

一般分為不帶參數的宏定義和帶參數的宏定義

不帶參數的宏定義

1、一般形式

#define 宏名 字元串

例:#define ABC 10

右邊的字元串也可以省略,比如#define ABC

2、作用

它的作用是在編譯預處理時,将源程式中所有”宏名”替換成右邊的”字元串”,常用來定義常量。

例:

#include <stdio.h>
#define Count 4

int main()
{
    int ages[Count] = {, , , };
    for ( int i = ; i<Count; i++) 
    {
        printf("%d\n", ages[i]);
    }
    return ;
}
           

輸出結果:

1

2

67

89

3、作用域

預處理指令可以出現在程式的任何位置

預處理指令的作用域:從編寫指令的那一行開始,一直到檔案結尾,可以用#undef取消宏定義的作用

例:

#include <stdio.h>
#define Count 4

int main()
{
    int ages[Count] = {, , , };
    for ( int i = ; i<Count; i++) 
    {
        printf("%d\n", ages[i]);
    }

    #undef Count; // 從此行開始取消宏定義的作用
    return ;
}
           

帶參數的宏定義

1、定義格式:

#define 宏名(參數清單) 字元串

#define sum(v1, v2) ((v1)+(v2))

2、使用注意—括号

例:定義平方的時候不加括号

#include <stdio.h>
#define pingfang(a) a*a // 未加括号

int main()
{
    int c = pingfang(+); // c = 5+5*5+5 = 35
    printf("c is %d\n", c);
    return ;
}
           

輸出結果:

c is 35

#include <stdio.h>
#define pingfang(a) ((a)*(a)) // 加括号

int main()
{
    int c = pingfang(+); // c = (5+5)*(5+5) = 100
    printf("c is %d\n", c);
    return ;
}
           

輸出結果:

c is 100

3、帶參數的宏定義與函數的差別

1> 宏定義不涉及存儲空間的配置設定、參數類型比對、參數傳遞、傳回值問題

2> 函數調用在程式運作時執行,而宏替換隻在編譯預處理階段進行,是以帶參數的宏比函數具有更高的執行效率

條件編譯

隻有當程式的其中一部分代碼在滿足一定條件時才進行編譯,否則不參與編譯(隻有參與編譯的代碼最終才能被執行)

基本用法

// 條件是對宏定義進行判斷
#if 條件
  ...code1... // 如果條件1成立,就把code1代碼編譯進去
#elif 條件
  ...code2... // 如果條件2成立,就把code2代碼編譯進去
#else
  ...code3... // 如果條件3成立,就把code3代碼編譯進去
#endif        // #endif不能少
           

例:

#include <stdio.h>
#define A 5

int main()
{
    #if (A == 10)
        printf("a是10\n");
    #elif (A == 5)
        printf("a是5\n");
    #else
        printf("a其他值\n");
    #endif
    return ;
}
           

運作結果:

a是5

if defined()和#if !defined()

判斷是否定義過某個宏

例:

// 如果定義了宏A,編譯code1
#if defined(A)
    ...code1...
#endif

// 如果沒有定義宏A,編譯code2
#if !defined(A)
    ...code2...
#endif
           

ifdef()和#ifndef()

#ifdef的使用和#if defined()的用法基本一緻

// 如果定義了宏A,編譯code1
#ifdef A 
    ...code1...
#endif
           

#ifndef又和#if !defined()的用法基本一緻

// 如果沒有定義宏A,編譯code2
#ifndef A
    ...code2...
#endif
           

檔案包含

一般形式

1、第1種形式

#include <檔案名>

直接到C語言庫函數頭檔案所在的目錄中尋找檔案

2、第2種形式

#include “檔案名”

系統會先在源程式目前目錄下尋找,若找不到,再到作業系統的path路徑中查找,最後才到C語言庫函數頭檔案所在目錄中查找

< >表示系統自帶的檔案,” “表示自定義的檔案

使用注意

#include指令允許嵌套包含,比如a.h包含b.h,b.h包含c.h,但是不允許遞歸包含,比如 a.h 包含 b.h,b.h 包含 a.h

關鍵字typedef

作用:給已經存在的類型起一個新的名稱

使用場合

基本資料類型

例:

#include <stdio.h>
typedef int MyInt; // 給int起了個别名Myint
int main() 
{
     MyInt a = -;
     printf("%d", a);
     return ;
}
           

指針

#include <stdio.h>
// 給指針類型char *起一個新的類型名稱String
typedef char * String;
int main()
{
    String str = "This is a string!";
    printf("%s", str);
    return ;
}
           

運作結果:

This is a string!

注意:“*”不能少

結構體

1、方式1

struct Student
{
    int age;
};
typedef struct Student MyStu;
           

2、方式2

typedef  struct Student
{
    int age;
} MyStu;
           

枚舉

1、方式1

enum Sex {Man, Woman};
typedef enum Sex MySex;
           

2、方式2

typedef enum {
    Man,
    Woman
} MySex;
           

指向函數的指針

#include <stdio.h>
typedef int (*MyPoint)(int, int);
int minus(int a, int b)
{
    return a - b;
}
int sum(int a, int b)
{
    return a + b;
}

int main()
{
    // 定義一個指向函數sum的指針p
    MyPoint p = sum;
    // 定義一個指向函數minus的指針p2
    MyPoint p2 = minus;
    // 利用指針變量p調用sum函數
    int a = (*p)(, );
    int b = (*p)(, );
    printf("%d,%d",a,b);
    return ;
}
           

運作結果:

9,7

typedef與#define

例:

typedef char *String1;
String1 str1, str2;
/* 
經過typedef處理後,String1也算是一種資料類型,是以第行代碼相當于:
String1 str1;
String1 str2;

由于String1就是char *,是以上面的兩行代碼等于:
char *str1;
char *str2;
*/

#define String2 char *
String2 str3, str4;
/*
因為宏定義純粹是字元串替換,用char *代替String2,是以相當于:
char * str3, str4;

其實也就相當于:
char * str3;
char str4;
*/
           

可以看出,隻有str4是基本資料類型,str1、str2、str3都是指針類型。

是以,以後給類型起别名,最好使用typedef,而不是使用#define