标准预处理指令 可变参数 #与## 的基本用法

news/2024/12/28 13:25:05/文章来源:https://www.cnblogs.com/DSCL-ing/p/18414577

目录
  • 举例一些的宏和预处理指令
    • C99引入的特性
      • VA_ARGS__
      • ##__VA_ARGS__
      • 说明:
    • #line
    • #error
    • #pragma
      • Message参数
      • #warning
  • #和##
    • 前置:相邻字符串具有自动连接特性
    • #运算符
      • #运算符的功能:在宏定义中,将宏参数转化成字符串
      • 用法举例:
      • 使用场景:
    • ##运算符
      • 功能:
      • 用法举例:

举例一些的宏和预处理指令

ANSI标准的5个预定义宏

__FILE__:当前文件名

__LINE__:所在行号

__STDC__:当编译器遵循ANSI C标准时该宏被定义为1。

__TIME__:表示当前源代码被编译的时间字符串。

__DATE__:表示当前源代码被编译的日期字符串。

C99引入的特性

  • 宏支持取可变参数 #define Macro(...) __VA_ARGS__
    __VA_ARGS__ 表示所有传递给宏的参数,可以是零个或多个参数
  • 使用宏的时候,允许省略参数,被省略的参数会被扩展成空串。
  • 除了已有的 __LINE____FILE__ 以外,增加了__func__得到当前的函数名。
  • 标准宏__STDC_VERSION__被定义为值199901L来指示能够获得C99支持。
#if __STDC_VERSION__ >= 199901L/* "inline" is a keyword */
#else
# define inline static
#endif
VA_ARGS__
  • __VA_ARGS__ 必须位于宏定义的参数列表中的最后。

  • __VA_ARGS__ 前后可以有其他参数,但至少要有一个参数,以便在没有传递额外参数时编译不会出错。

  • 传给__VA_ARGS__的多个参数,输出时会自动使用逗号分隔。

##__VA_ARGS__
  • 如果可变参数被忽略或为空,## 操作将使预处理器(preprocessor)去除掉它前面的那个逗号.
  • 如果你在宏调用时,确实提供了一些可变参数,GNU CPP 也会工作正常,它会把这些可变参数放到逗号的后面。
  • 这里的##功能不同于##运算符,注意区别.
#define LOG(...) printf("[%s:%d]" ,__FILE__,__LINE__,__VA_ARGS__)
int main()
{LOG(); //报错
}
#define LOG(...) printf("[%s:%d]" ,__FILE__,__LINE__,__VA_ARGS__)
int main()
{LOG(); //编译通过
}
说明:

__VA_ARGS__是一个傻傻的宏,在不定参前固定有一个逗号','因此会产生很多"反常"现象

  • 不定参为空时,"正常写法"编译器会报错

    预处理视角(右):__VA_ARGS__必带一个逗号

    image-20240729205043971

  • 不"正常"的正确写法

    image-20240729205459793

  • 日常写法

    image-20240729205611187


#line

可以定制化你的文件名称和代码行号,很少使用

image-20240508220935484


#error

#error命令是C/C++语言的预处理命令之一,当预处理器预处理到#error命令时将停止编译并输出用户自定义的错误消息。

image-20240508221706882

用于人为阻止编译,在某些情况下得知编译条件不满足时,可以使用#error让编译停止.


#pragma

#pragma 指令很复杂,需要使用的时候再查一下#pragma_百度百科 (baidu.com).

Message参数

Message 参数能够在编译信息输出窗口中输出相应的信息,这对于源代码信息的控制是非常重要的。其使用方法为:

#pragma message("消息文本")

当编译器遇到这条指令时就在编译输出窗口中将消息文本打印出来。

image-20240508222436848

也可以用于在编译器检测某个宏是否被定义:

image-20240508223051592

#warning
#pragma warning(disable:4996;once:4385;error:164)

等价于:

1#pragma warning(disable:4996)//不显示4996警告信息 
2#pragma warning(once:4385)//4385号警告信息仅报告一次 
3#pragma warning(error:164)//把164号警告信息作为一个错误。

还有很多用法..,可以查下文档

#pragma_百度百科 (baidu.com)

#和##

前置:相邻字符串具有自动连接特性

C语言两个相邻的字符串能够自动拼接成一个字符串.

int main()
{puts("hello"" world");const char *str = "hello"" world\n";printf(str);return 0;
}

image-20240509133454682


#运算符

#运算符的功能:在宏定义中,将宏参数转化成字符串

常搭配字符串连接特性一起使用

用法举例:
#define STR(s) #sint main()
{printf("PI: "STR(3.1415926)"\n");return 0;
}

image-20240509141118633

使用场景:
#define SQR(x) printf("The square of x is %d.\n", ((x)*(x)));int main()
{SQR(8);return 0;
}

image-20240509152413609

注意到没有,引号中的字符 x 被当作普通文本来处理,而不是被当作一个可以被替换的语言
符号。
假如你确实希望在字符串中包含宏参数,那我们就可以使用“#”,它可以把语言符号转
化为字符串。上面的例子改一改:

#define SQR(x) printf("The square of "#x" is %d.\n", ((x)*(x)));
再使用

SQR(8);
则输出的是:
image-20240509152653034


##运算符

功能:

​ 将宏参数与特定的符号组合成一个全新的符号

用法举例:

image-20240509151828264

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

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

相关文章

代码整洁之道--读书笔记(13)

代码整洁之道简介: 本书是编程大师“Bob 大叔”40余年编程生涯的心得体会的总结,讲解要成为真正专业的程序员需要具备什么样的态度,需要遵循什么样的原则,需要采取什么样的行动。作者以自己以及身边的同事走过的弯路、犯过的错误为例,意在为后来者引路,助其职业生涯迈上更…

读构建可扩展分布式系统:方法与实践08微服务

微服务1. 微服务 1.1. 微服务的起源可以追溯到2008年左右1.1.1. 在Amazon,​“两个比萨原则”成为一个单系统组件团队规模的管理原则,后来被称为微服务1.1.1.1. 每个内部团队都应该小到可以用两个比萨饼喂饱1.1.2. Amazon和Netflix是微服务架构的先驱,他们在2009年左右大规模…

C#|.net core 基础 - 值传递 vs 引用传递

文章探讨了C#中值传递与引用传递的概念及其对值类型和引用类型变量的影响。值传递创建参数副本,不影响原变量;引用传递共享内存地址,方法内修改影响原变量。特别提到string视为值类型处理,C#中ref、out等修饰符可实现引用传递。不知道你在开发过程中有没有遇到过这样的困惑…

浅谈舞蹈链(DLX)

名字: \(DL\),\(Dancing\space Link\),舞蹈链,是由\(Donald\space Knuth\)提出的数据结构,用来优化 \(X\) 算法,所以叫\(DLX\) \(X\)算法详解 用于求解精确覆盖问题,精确覆盖问题的定义:给定一个由0-1组成的矩阵,是否能找到一个行的集合,使得集合中每一列都恰好包含一…

java基础 -IO流笔记

610,文件的基础知识 文件流 输入流和输出流都是相对 java程序内存 而言611,创建文件 在D盘下创建文件。package com.hspedu.file;import org.junit.jupiter.api.Test; import java.io.File; import java.io.IOException;//演示创建文件 public class FileCreate {public sta…

2024软件工程个人作业(第二次)

这个作业属于哪个课程 https://edu.cnblogs.com/campus/fzu/SE2024这个作业要求在哪里 https://edu.cnblogs.com/campus/fzu/SE2024/homework/13253这个作业的目标 学会使用aigc编写学习代码,明白aigc能做哪些不能做哪些学号 1022014251. 项目展示 1.1. GitHub 仓库链接 ruang…

Kubernetes Ingress

目录一、为什么需要 Ingress二、什么是Ingress,Ingress Controller三、Ingress 的工作原理四、Ingress 配置资源模版五、实例1、搭建 Ingress 环境1.1、Ingress-Nginx官网地址1.2、master 节点下载 deploy.yaml1.3、所有节点提前 pull 必须的镜像1.4、修改并应用 deploy.yaml 文…

JVM--解析运行期优化与JIT编译器

JVM开发团队一直在努力,缩小Java与C/C++语言在运行效率上的差距。 本篇博客,我们来谈一谈JVM(HotSpot)为了提高Java程序的运行效率,都实现了哪些激动人心的技术~ 1 JIT编译器的引入 首先我们这篇文章中所说的编译器都是指JVM的组成部分之一---即时编译器(JIT),与生成J…

十七,Spring Boot 整合 MyBatis 的详细步骤(两种方式)

十七,Spring Boot 整合 MyBatis 的详细步骤(两种方式) @目录十七,Spring Boot 整合 MyBatis 的详细步骤(两种方式)1. Spring Boot 配置 MyBatis 的详细步骤2. 最后:MyBatis 的官方文档:https://mybatis.p2hp.com/ 关于 MyBatis 的学习的详细内容,大家可以移步至:✏️✏️…

学习高校课程-软件工程-软件流程(ch3)

3.1 A GENERIC PROCESS MODEL 通用过程模型 线性流和迭代流演化流和并行流3.2 DEFINING A FRAMEWORK ACTIVITY 定义框架活动 What actions are appropriate for a framework activity, given the nature of the problem to be solved, the characteristics of the people doing…