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 - Main 函数 C - 按值调用函数 C - 按引用调用函数 C - 嵌套函数 C - 可变参数函数 C - 用户定义函数 C - 回调函数 C - return 语句 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 - 指针 vs 数组 C - 字符指针和函数 C - NULL 指针 C - void 指针 C - 悬垂指针 C - 解引用指针 C - Near、Far 和 Huge 指针 C - 指针数组的初始化 C - 指针与多维数组

C 语言中的字符串

C - 字符串 C - 字符串数组 C - 特殊字符

C 语言的结构体和联合

C - 结构体 C - 结构体和函数 C - 结构体数组 C - 自引用结构 C - 查找表 C - 点 (.) 运算符 C - 枚举(或 enum) C - 结构填充和打包 C - 嵌套结构 C - 匿名结构和联合 C - 联合 C - Bit 位字段 C - Typedef

C 语言中的文件处理

C - 输入和输出 C - 文件 I/O(文件处理)

C 语言中的预处理器

C - 预处理器 C - #pragma 编译指示 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

如果定义了 DEBUG,则以下指令告诉 CPP 处理所附的语句。

#ifdef DEBUG
   /* Your debugging statements here */
#endif

如果您在编译时将 -DDEBUG 标志传递给 gcc 编译器,这将非常有用。这将定义 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
", __FILE__ );
   printf("Date: %s
", __DATE__ );
   printf("Time: %s
", __TIME__ );
   printf("Line: %d
", __LINE__ );
   printf("ANSI: %d
", __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!
")

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!
")

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
", 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
", MAX(10, 20));  
   return 0;
}

输出

运行此代码时,将产生以下输出 -

Max between 20 and 10 is 20