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

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.xdnf.cn/news/17865.html

相关文章:

  • 非中文语音视频自动生成中文字幕的完整实现方案
  • 38 C++ STL模板库7-迭代器
  • 电子电气架构 --- 线束设计一些事宜
  • 商城开发中,有哪些需要关注的网络安全问题
  • 【大模型微调系列-02】 深度学习与大模型初识
  • tun/tap 转发性能优化
  • 如何通过ETLCloud做数据监听
  • 北京JAVA基础面试30天打卡10
  • Unity与OpenGL中的材质系统详解
  • 电子电气架构 --- 探索软件定义汽车(SDV)的技术革新
  • 力扣326:3的幂
  • Ubuntu20.04下Px4使用UORB发布消息
  • OpenCV-循环读取视频帧,对每一帧进行处理
  • Qt——常用Widget(控件)
  • 【swift】SwiftUI动画卡顿全解:GeometryReader滥用检测与Canvas绘制替代方案
  • 有红帽认证证书可以0元置换华为openEuler-HCIA/HCIP认证
  • 醋酸镧:看不见的科技助力
  • 介绍TCP的拥塞控制
  • Oracle EBS R12.2 adlnkoh.sh执行报错
  • windows系统创建FTP服务
  • ar / let / const 以及不同写法的区别一
  • Vue 侦听器(watch 与 watchEffect)全解析2
  • [Chat-LangChain] 前端用户界面 | 核心交互组件 | 会话流管理
  • NY232NY236美光固态闪存NY240NY241
  • 责任链模式C++
  • 当云手机出现卡顿怎么办?
  • 第五天~提取Arxml中描述信息New_CanCluster--Expert
  • SpatialVLM和SpatialRGPT论文解读
  • 【进阶】Java技术栈八股文学习资料整理
  • Python 常用库速查手册