【C语言】宏定义详解

LuckiBit

目录

  • C语言宏定义详解
    • 1. 宏定义关键词总览
    • 2. `#define`
    • 3. `#undef`
    • 4. `#ifdef`
    • 5. `#ifndef`
    • 6. `#if`
    • 7. `#else`
    • 8. `#elif`
    • 9. `#endif`
    • 10. `#include`
    • 11. `#error`
    • 12. `#pragma`
      • 12.1 `#pragma once`
      • 12.2 `#pragma pack`
      • 12.3 `#pragma warning`
      • 12.4 `#pragma GCC`
    • 13. `#line`
    • 14. 字符串化和标识符连接
      • 14.1 字符串化(`#`)
      • 14.2 标识符连接(`##`)
    • 15. 总结
    • 16. 结束语
    • 相关文章:

C语言宏定义详解

在C语言中,宏定义是一种强大的预处理器功能,用于在编译之前对代码进行替换和条件编译。宏定义通过预处理器指令进行定义和使用,能够使代码更加灵活和可维护。本文将对C语言中的宏定义进行全面的讲解,包括各种相关的预处理器指令及其用法。

1. 宏定义关键词总览

关键词用途
#define定义宏(常量宏或函数宏)。
#undef取消(取消定义)一个先前定义的宏。
#ifdef检查某个宏是否已定义。
#ifndef检查某个宏是否未定义。
#if根据宏或表达式的值决定是否包含代码。
#else#if#ifdef#ifndef配合使用,提供条件不满足时的替代代码。
#elif提供额外的条件检查,类似于else if
#endif结束#if#ifdef#ifndef#elif块。
#include在当前文件中包含另一个文件,通常用于头文件的引入。
#error在预处理阶段生成错误信息并终止编译。
#pragma向编译器提供特定的指令或设置,依赖于编译器实现。
#line改变当前文件的行号和文件名,通常用于调试。
#将宏参数转换为字符串,称为字符串化操作符。
##在宏定义中连接两个标识符,称为标识符连接操作符。

2. #define

#define 指令用于定义宏,可以是常量宏或函数宏。常量宏用于定义常量值,而函数宏用于定义带参数的代码片段。

语法

#define MACRO_NAME replacement_text

示例

#define PI 3.14159
#define MAX(a, b) ((a) > (b) ? (a) : (b))

示例代码

#include <stdio.h>#define PI 3.14159
#define MAX(a, b) ((a) > (b) ? (a) : (b))int main() {printf("PI: %f\n", PI);printf("Max of 10 and 20: %d\n", MAX(10, 20));return 0;
}

输出

PI: 3.141590
Max of 10 and 20: 20

3. #undef

#undef 指令用于取消之前定义的宏,使其在后续代码中不再有效。

语法

#undef MACRO_NAME

示例

#include <stdio.h>#define TEMP 100
#undef TEMPint main() {// TEMP is no longer defined, so this will cause a compile error// printf("TEMP: %d\n", TEMP);return 0;
}

取消宏定义后,使用 TEMP 将导致编译错误,因为它不再被定义。

4. #ifdef

#ifdef 指令用于检查某个宏是否已定义。如果宏已定义,则编译相关的代码块。

语法

#ifdef MACRO_NAME// Code to be compiled if MACRO_NAME is defined
#endif

示例

#include <stdio.h>#define DEBUG#ifdef DEBUGprintf("Debug mode is on\n");
#endifint main() {return 0;
}

输出

Debug mode is on

5. #ifndef

#ifndef 指令用于检查某个宏是否未定义。如果宏未定义,则编译相关的代码块。

语法

#ifndef MACRO_NAME// Code to be compiled if MACRO_NAME is not defined
#endif

示例

#include <stdio.h>#ifndef VERSION
#define VERSION 1
#endifint main() {printf("Version: %d\n", VERSION);return 0;
}

输出

Version: 1

6. #if

#if 指令用于根据宏或表达式的值决定是否编译某些代码。它允许使用常量表达式进行条件判断。

语法

#if CONDITION// Code to be compiled if CONDITION is true
#endif

示例

#include <stdio.h>#define VERSION 2#if VERSION >= 2printf("Version is 2 or higher\n");
#endifint main() {return 0;
}

输出

Version is 2 or higher

7. #else

#else 指令用于在 #if#ifdef#ifndef 等条件编译指令中提供条件不满足时的替代代码。

语法

#if CONDITION// Code to be compiled if CONDITION is true
#else// Code to be compiled if CONDITION is false
#endif

示例

#include <stdio.h>#define DEBUG#ifdef DEBUGprintf("Debug mode is on\n");
#elseprintf("Debug mode is off\n");
#endifint main() {return 0;
}

输出

Debug mode is on

8. #elif

#elif 指令用于提供额外的条件检查,类似于 else if,用于在 #if#ifdef#ifndef 中增加更多的条件。

语法

#if CONDITION1// Code to be compiled if CONDITION1 is true
#elif CONDITION2// Code to be compiled if CONDITION2 is true
#endif

示例

#include <stdio.h>#define VERSION 2#if VERSION == 1printf("Version 1\n");
#elif VERSION == 2printf("Version 2\n");
#elseprintf("Other version\n");
#endifint main() {return 0;
}

输出

Version 2

9. #endif

#endif 指令用于结束一个由 #if#ifdef#ifndef#elif 等开始的条件编译块。

语法

#if CONDITION// Code to be compiled if CONDITION is true
#endif

示例

#include <stdio.h>#define VERSION 1#if defined(VERSION)printf("Version is defined\n");
#endifint main() {return 0;
}

输出

Version is defined

10. #include

#include 指令用于在当前文件中包含另一个文件,通常用于引入头文件。包括文件可以是系统文件或自定义文件。

语法

#include <filename>    // For system files
#include "filename"    // For user-defined files

示例

#include <stdio.h>
#include "myheader.h"int main() {return 0;
}

11. #error

#error 指令用于在预处理阶段生成错误信息并终止编译。它可以用于在编译过程中检测特定的条件并报告错误。

语法

#error error_message

示例

#include <stdio.h>#ifndef VERSION
#error "VERSION is not defined"
#endifint main() {return 0;
}

输出

VERSION is not defined

12. #pragma

#pragma 指令用于向编译器提供特定的指令或设置。#pragma 的具体行为依赖于编译器实现。以下是几个常见的 #pragma 示例:

12.1 #pragma once

用于防止头文件被多次包含。它确保头文件只会被处理一次。

示例

// myheader.h
#pragma oncevoid myFunction();

在多个源文件中包含 myheader.h 时,#pragma once 确保它只被处理一次。

12.2 #pragma pack

用于设置结构体对齐方式,控制结构体在内存中的对齐方式。

示例

#include <stdio.h>#pragma pack(push, 1)
typedef struct {char c;int i;
} MyStruct;
#pragma pack(pop)int main() {MyStruct ms;printf("Size of MyStruct: %zu\n", sizeof(ms));return 0;
}

在这个示例中,#pragma pack(push, 1) 指定了结构体 MyStruct 以1字节对齐,这会使 MyStruct 结构体的大小为5字节(1字节的 char 和4字节的 int)。#pragma pack(pop) 恢复之前的对齐设置。

输出

Size of MyStruct: 5

12.3 #pragma warning

用于控制编译器的警告信息,可以启用、禁用或设置警告级别。这些指令依赖于编译器,下面以 MSVC 编译器为例。

示例

#include <stdio.h>#pragma warning(push)
#pragma warning(disable: 4996)  // 禁用特定警告
#include <stdlib.h>
#pragma warning(pop)int main() {char str[10];sprintf(str, "Hello");printf("%s\n", str);return 0;
}

在这个示例中,#pragma warning(disable: 4996) 用于禁用有关不安全函数的警告,例如 sprintf 函数。#pragma warning(push)#pragma warning(pop) 保存和恢复警告状态。

输出

Hello

12.4 #pragma GCC

对于 GCC 编译器,#pragma GCC 允许控制一些 GCC 特性和行为。例如,可以禁用特定的优化警告。

示例

#include <stdio.h>#pragma GCC push_options
#pragma GCC optimize ("O0")  // 禁用优化
void foo() {printf("Function foo()\n");
}
#pragma GCC pop_optionsint main() {foo();return 0;
}

在这个示例中,#pragma GCC optimize ("O0") 禁用优化,这样 foo 函数不会被优化掉,可以用于调试。

输出

Function foo()

13. #line

#line 指令用于改变当前文件的行号和文件名,通常用于调试,帮助定位编译器生成的错误。

语法

#line line_number "file_name"

示例

#include <stdio.h>#line 100 "newfile.c"
int main() {printf("Current line: %d\n", __LINE__);return 0;
}

在这个示例中,#line 100 "newfile.c" 将当前行号设置为100,并将文件名设置为 newfile.c__LINE__ 预定义宏会返回设置的行号。

输出

Current line: 100

14. 字符串化和标识符连接

14.1 字符串化(#

字符串化操作符将宏参数转换为字符串。

语法

#define STRINGIFY(x) #x

示例

#include <stdio.h>#define STRINGIFY(x) #xint main() {printf("STRINGIFY(Hello): %s\n", STRINGIFY(Hello));return 0;
}

输出

STRINGIFY(Hello): Hello

14.2 标识符连接(##

标识符连接操作符将两个标识符连接成一个标识符。

语法

#define CONCAT(a, b) a##b

示例

#include <stdio.h>#define CONCAT(a, b) a##bint main() {int ab = 10;printf("Value of ab: %d\n", CONCAT(a, b));return 0;
}

输出

Value of ab: 10

15. 总结

C语言中的宏定义是一种强大的预处理器功能,用于在编译之前对代码进行替换和条件编译。通过使用 #define#undef#ifdef#ifndef#if#else#elif#endif#include#error#pragma 和其他指令,可以灵活地控制代码的编译过程。理解这些宏定义的用法可以帮助开发人员编写更加高效和可维护的代码。

16. 结束语

  1. 本节内容已经全部介绍完毕,希望通过这篇文章,大家对C语言宏定义有了更深入的理解和认识。
  2. 感谢各位的阅读和支持,如果觉得这篇文章对你有帮助,请不要吝惜你的点赞和评论,这对我们非常重要。再次感谢大家的关注和支持!点我关注❤️

相关文章:

  • 指针的神秘探险:从入门到精通的奇幻之旅 !

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/411597.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C# 对桌面快捷方式的操作设置开机启动项

首先在项目中引入Windows Script Host Object Model&#xff0c;引入方式如下图。 对于桌面快捷方式的修改无非就是将现有的快捷方式修改和添加新的快捷方式。 1、遍历桌面快捷方式&#xff0c;代码如下。 string desktopPath Environment.GetFolderPath(Environment.Special…

LLM 应用开发入门 - 实现 langchain.js ChatModel 接入火山引擎大模型和实现一个 CLI 聊天机器人(上)

前言 Langchain 是一个大语言模型(LLM)应用开发的框架,提供了 LLM 开发中各个阶段很多非常强大的辅助工具支持。对于进行 LLM 开发是必不可少的工具库。 本文将通过一个实际的开发例子来入门 LLM 开发基础工具链,并实现 langchain.js ChatModel 接入火山引擎大模型和基于…

【亲测有效】linux抓包http协议分析,分析header和body

linux抓包http协议分析&#xff0c;分析header和body 安装&#xff1a; 执行抓包命令&#xff0c;这里ip要换成你想抓包的目标ip&#xff1a; ngrep -q -W byline -d any "^Host:|^GET|^POST|^HTTP/" tcp and host 183.2.172.42 and port 80 触发抓包&#xff0c;…

FPGA实现多功能SDI视频采集卡,基于GTX+RIFFA架构,提供2套工程源码和技术支持

目录 1、前言工程概述免责声明 2、相关方案推荐我已有的PCIE方案本博已有的 SDI 编解码方案 3、详细设计方案设计框图SDI 输入设备Gv8601a 均衡器GTX 解串与串化SMPTE SD/HD/3G SDI IP核BT1120转RGBFDMA图像缓存RIFFA用户数据控制RIFFA架构详解Xilinx 7 Series Integrated Bloc…

94522

springboot 广州应用科技学院的教室管理系统 摘 要 科技进步的飞速发展引起人们日常生活的巨大变化&#xff0c;电子信息技术的飞速发展使得电子信息技术的各个领域的应用水平得到普及和应用。信息时代的到来已成为不可阻挡的时尚潮流&#xff0c;人类发展的历史正进入一个新时…

详细分析Ubuntu中的ufw基本知识

目录 前言1. 基本知识2. 基本使用 前言 由于命令行比较简单&#xff0c;此处主要以表格的形式呈现&#xff0c;还有实战中遇到的一个注意点 1. 基本知识 Ubuntu 中一种用户友好的防火墙配置工具&#xff0c;简化 iptables 的使用&#xff0c;适合那些不熟悉复杂防火墙配置的…

页面内容---复制粘贴【收藏版】【H5 web端亲测有效】

js中的复制粘贴 . 页面内容—复制粘贴【收藏版】【H5 web端亲测有效】 navigator.clipboard.writeText(copyText) 是 Web API 中的一个方法&#xff0c;用于将指定的文本内容复制到用户的剪贴板。这个方法属于 Clipboard API&#xff0c;它使得网页能够读取和写入剪贴板的内容…

开放式耳机哪种好用又实用?优质开放式耳机种草测评

在开放式耳机领域&#xff0c;目前有几款表现尤为突出的产品。作为一名专业的音乐制作人和评测专家&#xff0c;我深知一款出色的耳机对于音乐创作和鉴赏的重要性。 最近&#xff0c;我亲自评测了市面上一些颇受欢迎的开放式耳机&#xff0c;发现它们不仅在音质上有着令人满意…

winXP下构建python开发环境

近期车间有个动平衡检测仪数采的需求&#xff0c;工控机是xp系统&#xff0c;原理也很简单&#xff0c;监控文件变化&#xff0c;发现有新的检测数据就调用远程接口传输到服务器上去。 通常python监控文件变化会用watchdog这个库&#xff0c; 可是xp太老了&#xff0c;测试了一…

Jenkins服务安装配置

目录 Jenkins 配置环境 配置 中文插件 配置 Maven 插件 配置 JDK 配置 Git 配置 SSH 远程服务器 Jenkins 配置项目 构建 maven 项目 构建 pipeline 流水线项目 什么是 Jenkins Jenkins 是一个开源的自动化服务器&#xff0c;主要用于持续集成&#xff08;CI&#xff…

代码随想录刷题day15丨110.平衡二叉树,257. 二叉树的所有路径, 404.左叶子之和 ,222.完全二叉树的节点个数

代码随想录刷题day15丨110.平衡二叉树&#xff0c;257. 二叉树的所有路径&#xff0c; 404.左叶子之和 &#xff0c;222.完全二叉树的节点个数 1.题目 1.1平衡二叉树&#xff08;优先掌握递归&#xff09; 题目链接&#xff1a;110. 平衡二叉树 - 力扣&#xff08;LeetCode&a…

以小搏大:Salesforce 十亿参数模型表现超过ChatGPT

小模型的强势崛&#xff1a;轻量化AI如何以高效表现撼动大型模型的统治&#xff01; ©作者|DWT 来源|神州问学 导读 近年来&#xff0c;人工智能领域的迅猛发展使得大型语言模型&#xff08;LLM&#xff09;成为了焦点。这些模型&#xff0c;如OpenAI的GPT-4和Google的…

讲透一个强大的算法模型,Transformer

Transformer 模型是一种基于注意力机制的深度学习模型&#xff0c;广泛应用于自然语言处理&#xff08;NLP&#xff09;任务&#xff0c;如机器翻译、文本生成和语义理解。 它最初由 Vaswani 等人在2017年的论文《Attention is All You Need》中提出。它突破了传统序列模型&am…

CSRF 概念及防护机制

概述 CSRF&#xff08;Cross-Site Request Forgery&#xff09;&#xff0c;即跨站请求伪造&#xff0c;是一种网络攻击方式。在这种攻击中&#xff0c;恶意用户诱导受害者在不知情的情况下执行某些操作&#xff0c;通常是利用受害者已经登录的身份&#xff0c;向受害者信任的…

微纳芯:如何利用CRM实现渠道分销管理的数字化转型

MINCHIP由联想控股投资,是一家专注于快速体外诊断产品的研发、生产、销售、服务的高科技企业,拥有多项自主知识产权及技术专利。致力于用专业的微流控临床检验产品,为全球大众提供触手可及、负担得起的健康服务。其系列全自动生化分析仪持续为医师、兽医师的机构运营提供解决方…

C++对C的扩充(8.28)

1.使用C手动封装一个顺序表&#xff0c;包括成员数组1个&#xff0c;成员变量n个 代码&#xff1a; #include <iostream>using namespace std;//类型重命名 using datatype int; #define MAX 30struct seqList { private: //私有权限datatype *data; //相当于 …

Java中的java.lang.ArithmeticException: null问题详解与解决方案

个人名片 &#x1f393;作者简介&#xff1a;java领域优质创作者 &#x1f310;个人主页&#xff1a;码农阿豪 &#x1f4de;工作室&#xff1a;新空间代码工作室&#xff08;提供各种软件服务&#xff09; &#x1f48c;个人邮箱&#xff1a;[2435024119qq.com] &#x1f4f1…

fixed、absolute 和 relative 布局

https://andi.cn/page/621716.html

0.0 C语言被我遗忘的知识点

文章目录 位移运算(>>和<<)函数指针函数指针的应用场景 strcmp的返回值合法的c语言实数表示sizeof 数组字符串的储存 —— 字符数组与字符指针字符串可能缺少 \0 的情况 用二维数组储存字符串数组其他储存字符串数组的方法 位移运算(>>和<<) 右移(>…

什么是智能体(agent)

智能体&#xff08;Agent&#xff09;是人工智能领域中的一个核心概念。在最基本的层面上&#xff0c;智能体可以被定义为一个实体&#xff0c;它能够在其所处的环境中自主地感知信息&#xff0c;并根据这些信息做出决策&#xff0c;以实现特定的目标或任务。智能体的关键特性包…