当前位置: 首页 > news >正文

C语言基础00——基本补充(#define)

一、#define

        在 C 语言中,#define 是预处理指令的一种,主要用于在编译前对代码进行文本替换或定义宏,它的作用和用法可以从以下几个方面详细理解:

1.1 基本作用:文本替换

        #define的核心功能是在编译前将代码中所有出现的 “宏名” 替换为指定的 “替换文本”,这个过程称为 “宏展开”。

        语法格式:

#define 宏名 替换文本

示例

#include <stdio.h>
#define PI 3.14159  // 定义宏PI,替换文本为3.14159int main() {float radius = 2.0;float area = PI * radius * radius;  // 编译前会被替换为 3.14159 * radius * radiusprintf("面积: %f\n", area);return 0;
}

        运行结果:

        编译时,预处理阶段会先将代码中所有的 PI 替换为 3.14159,再进行后续编译。

1.2 无参数宏(符号常量)

        最常见的用法是定义 “符号常量”,用有意义的名称代替数值或字符串,提高代码的可读性和可维护性。

示例

#define MAX_SIZE 100  // 定义数组最大长度
#define GREET "Hello, World!"  // 定义字符串int main() {int arr[MAX_SIZE];  // 等价于 int arr[100];printf("%s\n", GREET);  // 等价于 printf("%s\n", "Hello, World!");return 0;
}

        运行结果:

        优势:如果需要修改 MAX_SIZE,只需修改 #define 一行,无需逐个修改代码中所有用到 100 的地方。

        注意:宏定义末尾不要加逗号,否则会被一起替换(例如 #define PI 3.14, 会导致替换后出现语法错误)。

1.3 带参数宏(类似函数的宏)

        #define可以定义带参数的宏,实现简单的代码片段替换,类似函数但没有函数调用的开销(宏是编译前替换,函数是运行时调用)。

        语法格式:

#define 宏名(参数列表) 替换文本

示例

// 定义求两数最大值的宏
#define MAX(a, b) (a > b ? a : b)#include <stdio.h>
int main() {int x = 5, y = 10;printf("最大值: %d\n", MAX(x, y));  // 替换为 (x > y ? x : y),输出10return 0;
}

运行结果:

注意事项

(1)替换文本中参数和整体需要加括号,避免优先级问题。

        例如,若定义为 #define MUL(a, b) a * b,当调用 MUL(2+3, 4) 时,会被替换为 2+3*4(结果 14),而非预期的 (2+3)*4(结果 20)。

        正确定义应为:#define MUL(a, b) ((a) * (b))。

(2)宏没有类型检查,而函数有严格的类型检查。例如 MAX("a", 3) 会在编译时出错,但宏本身不会检测参数类型。

(3)宏展开可能导致代码冗余。如果宏体较长,多次调用会导致编译后的代码体积增大(函数调用则不会)。

1.4 特殊用法

1.4.1 定义空宏

        用于条件编译的标记,本身没有替换文本,仅作为 “是否定义过” 的判断依据。

#define DEBUG  // 空宏,仅标记“已定义DEBUG”#ifdef DEBUG  // 如果DEBUG已定义,则执行下面的代码printf("调试信息: x = %d\n", x);
#endif

1.4.2 多行宏定义

        如果宏体需要换行,每行末尾加反斜杠 \(最后一行无需加)。

#define PRINT_INFO(name, age) \printf("姓名: %s\n", name); \printf("年龄: %d\n", age)// 调用
PRINT_INFO("张三", 20);  // 会展开为两行printf代码

1.4.3 字符串化(#)和连接(##

(1)#:将宏参数转换为字符串(字符串化)。

#define STR(s) #s
printf(STR(hello));  // 替换为 printf("hello");

(2)##:将两个符号连接为一个符号(令牌连接)。

#define JOIN(a, b) a##b
int num123 = 100;
printf("%d\n", JOIN(num, 123));  // 替换为 printf("%d\n", num123); 输出100

1.5 与 const 的区别

在 C 语言中,#define 定义的符号常量和 const 定义的常量有本质区别:

#define 是预处理阶段的文本替换,没有类型,不占用内存,作用域是从定义处到文件结束(可通过 #undef 取消定义)。

const 是编译阶段的常量,有明确类型,会占用内存(类似变量但值不可修改),受作用域和访问控制(如 static)限制。

示例

#define PI 3.14  // 无类型,预处理替换
const float pi = 3.14;  // 有float类型,编译时确定为常量

1.6 #define总结 

注意事项

        (1)宏定义通常放在文件开头,便于维护。

        (2)宏名一般用大写字母(如 MAX_SIZE),与变量名区分。

        (3)避免宏的副作用:例如 #define INC(x) x++,调用 INC(a + b) 会展开为 a + b++,导致逻辑错误。

        (4)可用 #undef 宏名 取消已定义的宏,避免冲突。

        总结来说,#define 是 C 语言中用于文本替换的预处理工具,灵活使用可以简化代码、提高可读性,但也需注意其无类型检查、可能引发优先级问题等特性,合理选择与 const 或函数配合使用。

http://www.dtcms.com/a/333068.html

相关文章:

  • useEffect 和 useLayoutEffect 执行时机
  • 【补充】数据库中有关系统编码和校验规则的简述
  • 网络性能排查
  • MC0439符号统计
  • 【web自动化】-2- 浏览器的操作和元素交互
  • 基于vue、node.js、express的网络教学系统设计与实现/基于vue、node.js、express的在线学习系统设计与实现
  • Python实现水文水质预测:Numpy/Matplotlib/TensorFlow实战+神经网络/CNN/RNN/SVM对比+大型水库案例
  • 【.net core】【wetercloud】处理前端项目免登陆,且从前端项目跳转至系统内时的问题
  • 【学习嵌入式day-25-线程】
  • 2020 GPT3 原文 Language Models are Few-Shot Learners 精选注解
  • git推送远程仓库报错:Bad configuration option: \357\273\277include
  • Git报错 “fatal: unable to access CRYPT_E_REVOCATION_OFFLINE (0x80092013)“问题的解决方法
  • 【CV 目标检测】②R-CNN模型
  • C# 中的计时器:Stopwatch 用法解析
  • diffusers学习--stable diffusion的管线解析
  • 第五天~提取Arxml的模板信息
  • react项目性能优化的hook
  • UGUI源码剖析(9):布局的实现——LayoutGroup的算法与实践
  • java程序打包成exe,再打成安装包,没有jdk环境下可运行
  • 【完整源码+数据集+部署教程】孔洞检测系统源码和数据集:改进yolo11-RetBlock
  • 金刚石基植入体新突破!Adv. Funct. Mater. 报道首例增材制造固态摩擦电能量收集器
  • 【FastGTP✨】[01] 使用 FastGPT 搭建简易 AI 应用
  • 部署Qwen-Image,通过API返回可访问的图像URL
  • 以下是对智能电梯控制系统功能及系统云端平台设计要点的详细分析,结合用户提供的梯控系统网络架构设计和系统软硬件组成,分点论述并补充关键要点:
  • 一文打通 AI 知识脉络:大语言模型等关键内容详解
  • 铨林接纸机学习记录1
  • AI智能文档生成系统需求规格说明书
  • Linux 进程、线程与 exec/系统调用详解
  • MySQL中的字符串函数
  • PowerShell 格式化系统完全掌握(下):自定义列/格式字符串/对齐与宽度 + 实战模板