
- C語言程式設計教程
- C語言 - 首頁
- C語言基礎
- C語言 - 概述
- C語言 - 特性
- C語言 - 歷史
- C語言 - 環境搭建
- C語言 - 程式結構
- C語言 - Hello World
- C語言 - 編譯過程
- C語言 - 註釋
- C語言 - 詞法單元
- C語言 - 關鍵字
- C語言 - 識別符號
- C語言 - 使用者輸入
- C語言 - 基本語法
- C語言 - 資料型別
- C語言 - 變數
- C語言 - 整數提升
- C語言 - 型別轉換
- C語言 - 型別強制轉換
- C語言 - 布林值
- C語言中的常量和字面量
- C語言 - 常量
- C語言 - 字面量
- C語言 - 轉義序列
- C語言 - 格式說明符
- C語言中的運算子
- C語言 - 運算子
- C語言 - 算術運算子
- C語言 - 關係運算符
- C語言 - 邏輯運算子
- C語言 - 位運算子
- C語言 - 賦值運算子
- C語言 - 一元運算子
- C語言 - 自增和自減運算子
- C語言 - 三元運算子
- C語言 - sizeof運算子
- C語言 - 運算子優先順序
- C語言 - 其他運算子
- C語言中的決策機制
- C語言 - 決策機制
- C語言 - if語句
- C語言 - if...else語句
- C語言 - 巢狀if語句
- C語言 - switch語句
- C語言 - 巢狀switch語句
- C語言中的迴圈
- C語言 - 迴圈
- C語言 - while迴圈
- C語言 - for迴圈
- C語言 - do...while迴圈
- C語言 - 巢狀迴圈
- C語言 - 死迴圈
- C語言 - break語句
- C語言 - continue語句
- C語言 - goto語句
- C語言中的函式
- C語言 - 函式
- C語言 - 主函式
- C語言 - 按值呼叫函式
- C語言 - 按引用呼叫函式
- C語言 - 巢狀函式
- C語言 - 可變引數函式
- C語言 - 使用者自定義函式
- C語言 - 回撥函式
- C語言 - 返回語句
- C語言 - 遞迴
- C語言中的作用域規則
- C語言 - 作用域規則
- C語言 - 靜態變數
- C語言 - 全域性變數
- C語言中的陣列
- C語言 - 陣列
- C語言 - 陣列的特性
- C語言 - 多維陣列
- C語言 - 將陣列傳遞給函式
- C語言 - 從函式返回陣列
- C語言 - 變長陣列
- C語言中的指標
- C語言 - 指標
- C語言 - 指標和陣列
- C語言 - 指標的應用
- C語言 - 指標運算
- C語言 - 指標陣列
- C語言 - 指向指標的指標
- C語言 - 將指標傳遞給函式
- C語言 - 從函式返回指標
- C語言 - 函式指標
- C語言 - 指向陣列的指標
- C語言 - 指向結構體的指標
- C語言 - 指標鏈
- C語言 - 指標與陣列的區別
- C語言 - 字元指標和函式
- C語言 - 空指標
- C語言 - void指標
- C語言 - 懸空指標
- C語言 - 解引用指標
- C語言 - 近、遠和巨型指標
- C語言 - 指標陣列的初始化
- C語言 - 指標與多維陣列的區別
- C語言中的字串
- C語言 - 字串
- C語言 - 字串陣列
- C語言 - 特殊字元
- C語言中的結構體和聯合體
- C語言 - 結構體
- C語言 - 結構體和函式
- C語言 - 結構體陣列
- C語言 - 自引用結構體
- C語言 - 查詢表
- C語言 - 點(.)運算子
- C語言 - 列舉(enum)
- C語言 - 結構體填充和打包
- C語言 - 巢狀結構體
- C語言 - 匿名結構體和聯合體
- C語言 - 聯合體
- C語言 - 位域
- C語言 - typedef
- C語言中的檔案處理
- C語言 - 輸入與輸出
- C語言 - 檔案I/O(檔案處理)
- C語言預處理器
- C語言 - 預處理器
- C語言 - 預處理指令
- C語言 - 預處理器運算子
- C語言 - 宏
- C語言 - 標頭檔案
- C語言中的記憶體管理
- C語言 - 記憶體管理
- C語言 - 記憶體地址
- C語言 - 儲存類別
- 其他主題
- C語言 - 錯誤處理
- C語言 - 可變引數
- C語言 - 命令執行
- C語言 - 數學函式
- C語言 - static關鍵字
- C語言 - 隨機數生成
- C語言 - 命令列引數
- C語言程式設計資源
- C語言 - 問答
- C語言 - 快速指南
- C語言 - 速查表
- C語言 - 有用資源
- C語言 - 討論
C語言預處理器
C預處理器不是編譯器的一部分,而是編譯過程中的一個單獨步驟。簡單來說,C預處理器只是一個文字替換工具,它指示編譯器在實際編譯之前進行必要的預處理。我們將C預處理器稱為CPP。
在C程式設計中,預處理是C程式碼編譯的第一步。它發生在詞法分析步驟之前。預處理器的重要功能之一是包含包含程式中使用的庫函式的標頭檔案。C語言中的預處理器還定義常量並展開宏。
C語言中的預處理器語句稱為指令。程式的預處理器部分始終出現在C程式碼的頂部。每個預處理器語句都以井號(#)符號開頭。
C語言中的預處理器指令
下表列出了所有重要的預處理器指令:
指令 | 描述 |
---|---|
# define | 替換預處理器宏。 |
#include | 插入來自另一個檔案的特定標頭檔案。 |
#undef | 取消定義預處理器宏。 |
#ifdef | 如果此宏已定義,則返回true。 |
#ifndef | 如果此宏未定義,則返回true。 |
#if | 測試編譯時條件是否為真。 |
#else | #if 的替代方案。 |
#elif | #else 和 #if 合併成一個語句。 |
#endif | 結束預處理器條件。 |
#error | 在stderr上列印錯誤訊息。 |
#pragma | 使用標準化的方法向編譯器發出特殊命令。 |
預處理器示例
分析以下示例以瞭解各種指令。
此#define指令告訴CPP將MAX_ARRAY_LENGTH的所有例項替換為20。使用#define定義常量以提高可讀性。
#define MAX_ARRAY_LENGTH 20
以下指令告訴CPP從系統庫中獲取“stdio.h”並將文字新增到當前原始檔中。下一行告訴CPP從本地目錄獲取“myheader.h”並將內容新增到當前原始檔中。
#include <stdio.h> #include "myheader.h"
現在,讓我們看一下以下#define和#undef指令。它們告訴CPP取消定義現有的FILE_SIZE並將其定義為42。
#undef FILE_SIZE #define FILE_SIZE 42
以下指令告訴CPP僅在MESSAGE未定義時定義MESSAGE。
#ifndef MESSAGE #define MESSAGE "You wish!" #endif
以下指令告訴CPP如果定義了DEBUG,則處理包含的語句。
#ifdef DEBUG /* Your debugging statements here */ #endif
如果您在編譯時向gcc編譯器傳遞-DDEBUG標誌,這將很有用。這將定義DEBUG,因此您可以在編譯過程中動態地開啟和關閉除錯。
C語言中的預定義宏
ANSI C定義了許多宏。儘管每個宏都可用於程式設計,但不應直接修改預定義宏。
宏 | 描述 |
---|---|
__DATE__ | 當前日期,以“MMM DD YYYY”格式的字元字面量表示。 |
__TIME__ | 當前時間,以“HH:MM:SS”格式的字元字面量表示。 |
__FILE__ | 包含當前檔名,作為字串字面量。 |
__LINE__ | 包含當前行號,作為十進位制常量。 |
__STDC__ | 當編譯器符合ANSI標準時定義為1。 |
示例
讓我們嘗試以下示例:
#include <stdio.h> int main(){ printf("File: %s\n", __FILE__ ); printf("Date: %s\n", __DATE__ ); printf("Time: %s\n", __TIME__ ); printf("Line: %d\n", __LINE__ ); printf("ANSI: %d\n", __STDC__ ); }
輸出
執行此程式碼時,將產生以下輸出:
File: main.c Date: Mar 6 2024 Time: 13:32:30 Line: 8 ANSI: 1
預處理器運算子
C預處理器提供以下運算子來幫助建立宏:
示例:C語言中的宏續接符(\)運算子
宏通常限制在一行內。宏續接符(\)用於繼續過長而無法在一行中容納的宏。請看下面的例子:
#include <stdio.h> #define message_for(a, b) \ printf(#a " and " #b ": We love you!\n") int main() { message_for(Ram, Raju); }
輸出
執行此程式碼時,將產生以下輸出:
Ram and Raju: We love you!
示例:C語言中的字串化(#)運算子
字串化運算子(#),也稱為井號運算子,在宏定義中使用時,會將宏引數轉換為字串常量。
字串化運算子只能用於具有指定引數列表的宏。例如:
#include <stdio.h> #define message_for(a, b) \ printf(#a " and " #b ": We love you!\n") int main() { message_for(Carole, Debra); return 0; }
輸出
執行程式碼並檢查其輸出:
Carole and Debra: We love you!
示例:C語言中的標記貼上(##)運算子
宏定義中的標記貼上運算子(##)組合兩個引數。它允許宏定義中的兩個單獨標記連線成一個標記。例如:
#include <stdio.h> #define tokenpaster(n) printf ("token" #n " = %d", token##n) int main() { int token34 = 40; tokenpaster(34); return 0; }
輸出
執行此程式碼時,將產生以下輸出:
token34 = 40
示例:C語言中的defined()運算子
預處理器defined運算子用於常量表達式中,以確定是否使用#define定義了識別符號。如果指定了識別符號,則值為true(非零)。如果符號未定義,則值為false(零)。
以下示例演示如何在C程式中使用defined運算子:
#include <stdio.h> #if !defined (MESSAGE) #define MESSAGE "You wish!" #endif int main() { printf("Here is the message: %s\n", MESSAGE); return 0; }
輸出
執行程式碼並檢查其輸出:
Here is the message: You wish!
C語言中的引數化宏
CPP的強大功能之一是能夠使用引數化宏來模擬函式。例如,我們可能有如下計算平方數的程式碼:
int square(int x) { return x * x; }
我們可以使用宏重寫上述程式碼,如下所示:
#define square(x) ((x) * (x))
帶引數的宏必須在使用之前使用#define指令定義。引數列表括在括號中,並且必須緊跟在宏名之後。宏名和左括號之間不允許有空格。
示例
以下示例演示如何在C語言中使用引數化宏:
#include <stdio.h> #define MAX(x,y) ((x) > (y) ? (x) : (y)) int main() { printf("Max between 20 and 10 is %d\n", MAX(10, 20)); return 0; }
輸出
執行此程式碼時,將產生以下輸出:
Max between 20 and 10 is 20