C语言 宏

目录

一、宏定义

1.1 预定义符号

1.2 预处理指令 #define

1.3 带有副作用宏定义

1.4 宏和函数的一个对比

​编辑

1.5 #undef

二、条件编译

2.1 #if、#else、#elif、#endif

2.2 #ifdef和#ifndef

2.3 C语言中如何通过条件编译来预防头文件的重复包含?


一、宏定义

在C语言中,宏定义是通过  #define 关键字实现的,它可以将被定义的标识符替换为相应的字符串或代码片段。宏定义主要用于简化代码、提高程序的通用性和易读性,同时也能在一定程度上提高程序的运行效率

1.1 预定义符号

在C语言中,预定义符号是由编译器提供的,它们具有特殊的含义和功能。

以下是C语言中的一些常见预定义符号及其用途:

  • __FILE__:表示当前源文件的文件名,可用于调试时显示文件名。 
  • __LINE__:表示当前代码所在的行号,可用于调试时显示代码位置。 
  • __DATE__:表示当前编译的日期,格式为"MMM DD YYYY",例如"Jul 29 2023"。 
  • __TIME__:表示当前编译的时间,格式为"HH:MM:SS",例如"10:30:36"。 
  • __STDC__:如果编译器遵循ANSI C标准,其值为1,否则未定义。这个符号通常用于检测编译器的兼容性。

在VS中(__STDC__)未定义,所以该编译器不支持ANSC l 标准,如下图:

1.2 预处理指令 #define

宏定义主要有两种类型:

  • 不带参数的宏定义和。
  • 带参数的宏定义。

不带参数的宏定义简单地将宏名替换为定义的字符串,例如:

#define PI 3.14159

带参数的宏定义除了进行简单的文本替换外,还会对参数进行计算。例如:

#define S(a,b) a*b

#define 定义的规则

  • 宏替换发生在预处理阶段,即编译前
  • 宏替换是简单的文本替换,不涉及计算
  • 宏替换不占用运行时间,只占用编译时间

1.3 # 和 ##

#操作符用于预编译时期,将宏参数转换为字符串。如图:

##操作符用于在预编译期间将两个宏参数连接起来,形成一个单独的标识符。如图:

1.3 带有副作用宏定义

例如,假设有一个宏定义MAX(a, b),它在预处理阶段展开为((a) > (b) ? (a) : (b))。如果使用MAX(x++, y++),预处理后的结果将是((x++) > (y++) ? (x++) : (y++))。这意味着xy都将被自增两次,这可能并非程序员原本的意图。

正常情况下:

带有副作用情况下:

  • ret 返回的是7,自增了一次,在问好(?)前面。
  • a 的值是3 ,自增了一次,在问号(?)前面。
  • b 的值是8,自增了两次,在则问号前后各增加一次。
1.4 宏和函数的一个对比

相比之下,宏在预编译阶段将宏名替换为后面的替换体,避免了函数调用的开销。宏的展开是简单的文本替换,没有类型检查,因此可能会导致一些潜在的错误。然而,宏的使用可以提高代码的可读性和可维护性,并且在某些情况下,宏的使用可以提高程序的效率。

1.5 #undef

#undef是C语言预处理指令的一种,它的作用是取消之前通过#define指令定义的宏或符号常量

#include <stdio.h>int main() {#define MAX 200printf("MAX = %d\n", MAX);#undef MAXint MAX = 10;printf("MAX = %d\n", MAX);return 0;
}

二、条件编译

条件编译的主要指令包括#if#else#elif#endif#ifdef#ifndef

2.1 #if#else#elif#endif
  • #if用于判断表达式是否为真,如果为真则编译其后的代码;
  • #else用于与#if搭配,当前面的条件不满足时,编译#else后的代码;
  • #elif相当于#else#if的结合,用于多个条件中的其他条件
  • #endif用于结束一个条件编译块;
2.2 #ifdef#ifndef

#ifndef#ifdef相反,用于判断一个宏是否未被定义,如果未被定义则编译其后的代码。

2.3 C语言中如何通过条件编译来预防头文件的重复包含?

1、使用#ifndef、#define、#endif预处理指令

#ifndef MY_HEADER_H
#define MY_HEADER_H
// 头文件内容
#endif

当头文件第一次被包含时,由于没有定义MY_HEADER_H,编译器会执行#define指令,定义该宏。当头文件再次被包含时,由于该宏已被定义,编译器会跳过#ifndef#endif之间的代码,从而避免重复包含。

2、使用#pragma once指令:

#pragma once
// 头文件内容

这种方法的好处是不会出现宏名冲突的问题,且对于大型项目来说,可以提高编译速度。 

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

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

相关文章

导弹初识(一)

目录 导弹初识1 导弹是什么2 导弹的分类2.1 按飞行方式2.2 按发射/目标2.2.1 空空导弹2.2.1 空地导弹2.2.1 地空导弹2.2.1 地地导弹 2.3 按打击目标 3.实例3.1 防空导弹3.2 低空防空导弹武器系统 本文节选自 zh&#xff0c;还有百度百科 导弹初识 1 导弹是什么 导弹两个字拆…

欧拉函数、快速幂、扩展欧几里得算法、中国剩余定理和高斯消元

欧拉函数 给定 n 个正整数 ai&#xff0c;请你求出每个数的欧拉函数。 欧拉函数的定义1∼N 中与 N 互质的数的个数被称为欧拉函数&#xff0c;记为 ϕ(N)。 若在算数基本定理中&#xff0c;Np1a11p2a2…pmm&#xff0c;则&#xff1a;ϕ(N) Np1−1/p1p2−1/p2…pm−1/pm 输…

二叉树基于队列实现的操作详解

一、队列知识补充 有关队列的知识请详见博主的另一篇博客&#xff1a;http://t.csdnimg.cn/3PwO4 本文仅仅附上需要的队列操作供读者参考 //结构体定义 typedef struct BinaryTreeNode* QDataType;typedef struct QueueNode {struct QueueNode* next;QDataType val; }QNode;…

添砖Java(十一)——常见类的使用Object,Math,System,BigDeciaml,包装类

目录 object&#xff1a; toString&#xff1a; equals: ​编辑 Math&#xff1a;​编辑 System: BigDecimal: 基本数据的包装类&#xff1a;​编辑 object&#xff1a; 我们知道&#xff0c;所有的类都是间接或直接继承了object类。然后object里面有几个用得很多的方法…

7.2k star的万能视频解析下载插件

今天给大家介绍一个超级厉害的浏览器插件&#xff0c;可以解析各个平台网页视频——猫抓。 项目简介 猫抓&#xff08;cat-catch&#xff09; 是一款资源嗅探扩展插件&#xff0c;他能够帮助你筛选列出当前页面的资源。简单来说&#xff0c;当你打开任意一个带有视频的网页&a…

信息系统项目管理师十大管理计划内容概览

目录 1.项目章程2.项目管理计划3.范围管理计划4.需求管理计划5.进度管理计划6.成本管理计划7.质量管理计划8.资源管理计划9.沟通管理计划10.风险管理计划11.采购管理计划12.干系人参与计划 点我去AIGIS公众号查看本文 1.项目章程 项目目标成功标准退出标准关键干系人名单发起人…

Android9.0 MTK平台如何增加一个系统应用

在安卓定制化开发过程中&#xff0c;难免遇到要把自己的app预置到系统中&#xff0c;作为系统应用使用&#xff0c;其实方法有很多&#xff0c;过程很简单&#xff0c;今天分享一下我是怎么做的&#xff0c;共总分两步&#xff1a; 第一步&#xff1a;要找到当前系统应用apk存…

Linux_应用篇(08) 信号-基础

本章将讨论信号&#xff0c;虽然信号的基本概念比较简单&#xff0c;但是其所涉及到的细节内容比较多&#xff0c;所以本章篇幅也会相对比较长。 事实上&#xff0c;在很多应用程序当中&#xff0c;都会存在处理异步事件这种需求&#xff0c;而信号提供了一种处理异步事件的方法…

c# 画一个正弦函数

1.概要 c# 画一个正弦函数 2.代码 using System; using System.Drawing; using System.Windows.Forms;public class SineWaveForm : Form {private const int Width 800;private const int Height 600;private const double Amplitude 100.0;private const double Period…

lvgl无法显示中文

环境&#xff1a; VS2019、LVGL8.3 问题&#xff1a; VS2019默认编码为GB2312&#xff0c; 解决&#xff1a; VS2022设置编码方式为utf-8的三种方式_vs utf8-CSDN博客 我用的方法2&#xff0c;设置为 utf-8无签名就行。

深入了解Socket套接字

目录 一、引入&#x1f64c; 1、概念 &#x1f389; 2、分类&#x1f389; Socket 套接字主要针对传输层协议分为流套接字、数据报套接字、原始套接字&#xff08;了解即可&#xff09;三类。 1&#xff09;流套接字&#xff1a;使用传输层TCP协议 2&#xff09;数据报套…

AI预测福彩3D采取888=3策略+和值012路一缩定乾坤测试5月25日预测第1弹

上一套算法采用了88723的容差策略&#xff0c;关于容差策略相信大家都比较清楚&#xff1a;容差可以最大限度的保证初始大底中包含中奖号码&#xff0c;然后再通过设置一些杀号条件进行缩水。比如&#xff0c;我对我的各种模型算法近30期的预测结果进行了统计&#xff0c;如果采…

huggingface笔记: accelerate estimate-memory 命令

探索可用于某一机器的潜在模型时&#xff0c;了解模型的大小以及它是否适合当前显卡的内存是一个非常复杂的问题。为了缓解这个问题&#xff0c;Accelerate 提供了一个 命令行命令 accelerate estimate-memory。 accelerate estimate-memory {MODEL_NAME} --library_name {LIBR…

Stable Diffusion【艺术特效】【霓虹灯】:霓虹灯像素化马赛克特效

提示词 Neon pixelated mosaic of [Subject Description],highly detailed [主题]的霓虹灯像素化马赛克&#xff0c;高度详细 参数设置 大模型&#xff1a;万享XL_超写实摄影V8.2 采样器&#xff1a;Euler a 采样迭代步数&#xff1a;25 CFG&#xff1a;3 反向提示词&#x…

微服务可用性之隔离

摘要 ​ 本文主要微服务场景下服务的可用性保障之隔离。隔离又分为几种情况&#xff0c;动静隔离、读写隔离、热点隔离、资源隔离等场景。 为什么要隔离 ​ 本质上是对资源进行分割确保在出现故障的时候服务只是部分不可用&#xff0c;不至于系统陷入整体性瘫痪&#xff0c;…

使用C/C++ API接口操作 Zookeeper 数据

ZooKeeper 支持 Java 和 C 的API接口。本文将介绍使用 C/C 语言客户端库的编译安装和使用入门。 一、编译安装 PS&#xff1a;就在上一篇文章还觉得安装和配置 jdk 、maven 麻烦&#xff0c;所以当时选择 apache-zookeeper-[version]-bin.tar.gz 的版本。然而&#xff0c;本文…

Leetcode刷题笔记4

1658. 将 x 减到 0 的最小操作数 1658. 将 x 减到 0 的最小操作数 - 力扣&#xff08;LeetCode&#xff09; 示例 3&#xff1a; 输入&#xff1a;nums [3,2,20,1,1,3], x 10 输出&#xff1a;5 解释&#xff1a;最佳解决方案是移除后三个元素和前两个元素&#xff08;总共…

【CAN】STM32新能源汽车CAN通信实现过程

【CAN】STM32新能源汽车CAN通信实现过程 文章目录 前言一、软件1.PA11、PA12口配置2.PB8、PB9口配置 二、接线图三、硬件原理图四、上位机总结 前言 【电机控制】直流有刷电机、无刷电机汇总——持续更新 使用工具&#xff1a; 1.控制器——STM32F103C8T6 2.仿真器——STLINK …

Opencompass模型评测教程

模型评测 模型评测非常关键&#xff0c;目前主流的方法主要可以概括为主观评测和客观评测&#xff0c;主观评测又可以分为两种形式&#xff1a;人工判断或者和模型竞技场。客观评测一般采用评测数据集的形式进行模型评测。本教程使用Opencompass工具进行对Internlm2-7b模型进行…

网络模型-策略路由配置

在实际网络应用中&#xff0c;策略路由也是一种重要的技术手段。尽管在考试并不注重策略路由&#xff0c;但是实际上应用较多建议考生除了掌握基本的静态路由协议IP route-static&#xff0c;动态路由协议RIP、还要掌握如何配置策略路由。策略路由的基本原理:根据ACL定义的不同…