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

C++中的宏

0 资料

  • 最值宏
  • do{}while(0)的宏封装技巧

1 最值宏

- C++最值的宏,在两个头文件中,分别为cfloat和climits。其中,float的最值宏在cfloat中,且cfloat没有负值的最小宏,而其他char、int和double是在climits中。如下
// --------------------------------
#include <limits.h>CHAR_MIN        char的最小值
SCHAR_MAX        signed char 最大值
SCHAR_MIN        signed char 最小值
UCHAR_MAX        unsigned char 最大值SHRT_MAX        short 最大值
SHRT_MIN        short 最小值
USHRT_MAX        unsigned short 最大值INT_MAX        int 最大值
INT_MIN         int 最小值
UINT_MAX        unsigned int 最大值
UINT_MIN        unsigned int 最小值LONG_MAX        long最大值
LONG_MIN        long最小值
ULONG_MAX        unsigned long 最大值double d1 = DBL_MIN;
double d2 = DBL_MAX;
long ln1 =  LONG_MAX;
long ln2 =  LONG_MIN;
long long lln1 = LONG_LONG_MAX;
long long lln1 = LONG_LONG_MIN;// --------------------------------
#include <float.h> 
FLT_MANT_DIG      float 类型的尾数
FLT_DIG         float 类型的最少有效数字位数
FLT_MIN_10_EXP     带有全部有效数的float类型的负指数的最小值(以10为底)
FLT_MAX_10_EXP      float类型的正指数的最大值(以10为底)
FLT_MIN         保留全部精度的float类型正数最小值
FLT_MAX         float类型正数最大值

2 定位宏

  • FILE:文件名
  • FUNCTION:函数名
  • LINE:行数

3 比较宏

  • 在C/C++中,浮点数的表示是不准确的。float、double分别遵循R32-24,R64-53的标准。他们尾数的位数分别是23、52,即误差在2-23,2-52.所以float的精度误差在1e-6,double的精度误差在1e-15。因此,对于浮点数的比较不能单纯使用==与!=来比较。通常使用以下的比较方法:
    • 所以判断浮点数是否等于0:
      • 要判断一个单精度浮点数是否等于0:if(fabs(f_float) <= 1e-6);
      • 要判断一个双精度浮点数是否等于0:if(fabs(d_double) <= 1e-15);
    • 所以判断两个浮点数相等:
      • 要判断两个单精度浮点数是否相等:if(fabs(f1_float - f2_float) <= 1e-6);
      • 要判断两个双精度浮点数是否相等:if(fabs(d1_double - d2_double) <= 1e-15);
    • 注意:
      • 浮点数的绝对值用fabs(整型绝对值是abs)
      • fabs与abs是在cmath头文件中

4 连接宏

4.1 #运算符

#运算符用于创建字符串,简单说就是在它引用的宏变量的左右各加上一个双引号。#运算符后面应该跟一个形参(中间可以有空格或Tab),

如定义好#define STRING(x) #x之后,下面二条语句就等价。

char *pChar = "hello world";
char *pChar = STRING(hello world);

4.2 #@运算符

在函数式宏定义中,#@运算符用于创建一个字符,如

#define makechar(x)  #@xa = makechar(b);

预处理之后是 a = ‘b’;

4.3 ##运算符

##运算符把前后两个预处理Token连接成一个预处理Token,和#运算符不同:##运算符不仅限于函数式宏定义,变量式宏定义也可以用。例如:

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

预处理之后是concat。再比如,要定义一个宏展开成两个#号,可以这样定义:

#define HASH_HASH # ## #

注意

凡是宏定义里有用**#或##的地方宏参数是不会再展开**,例如**_STRI(INT_MAX)中的INT_MAX就不会被展开为2147483647**。

如果想要使其中的宏参数展开,则需要多加一层中间转换宏: #define STRI(s) _STRI(s)。加这层宏的用意是把所有宏的参数在这层里全部展开,那么在转换宏里的宏就能得到对应的宏参数。

#include<stdio.h>
#include<iostream>
using namespace std;#define f(a,b) a##b
#define g(a) #a
#define h(a) g(a)#define A(x) T_##x
#define B(x) #@x
#define C(x) #x#define WARN_IF(EXP) if(EXP) cerr << #EXP << endl;
#define paster( n ) cout << "token" << #n << " = " << n << endl;
#define _CONS(a, b) int(a##+##b)
#define _STRI(s) #s
#define STRI(s) _STRI(s)void test_sharp_symbol()
{printf("%s\n", h(f(1, 2))); //输出:12printf("%s\n", g(f(1, 2))); //输出:f(1,2)printf("%s\n", h(A(1)));    // A(1)------〉T_1printf("%d\n", B(1));       // B(1)------〉'1'printf("%s\n", C(1));       // C(1)------〉"1"int div = 0;WARN_IF(div == 0);              //输出: div == 0paster(9);                      //输出: token9 = 9cout << _CONS(1+2, 2) << endl;  //输出: 3cout << _STRI(INT_MAX) << endl; //输出: INT_MAXcout << STRI(INT_MAX) << endl; // prints : 2147483647
}
  • Token 是程序中对编译器有意义的最小元素。Token 可分类如下:
    • Keywords
    • Identifiers
    • Constants
    • Strings
    • Special Symbols
    • Operators


自定义宏

易错点

  • 宏函数,要使用do{}while(0)的技巧,将函数体存为复合语句,相当于单条语句。避免宏替换对一些语句造成执行逻辑的错误,例如if、while等,参考博客,例如
#ifndef xxx
#defind xxx(v) do{...;...;}while(0)
#endif

注意,while后面不要加分号( ; )。

  • 宏函数中,要注意多次替换输入参数的问题。如果输入参数是个函数,而该参数在宏函数体中出现多次,则函数体会被实现多次,这是很严重的错误。

相关文章:

  • 解码数据语言:如何优雅的进行数仓字典建设?
  • Web开发-Python应用Flask框架Jinja模版绑定路由参数传递页面解析SSTI注入
  • 协程+Flow:现代异步编程范式,替代RxJava的完整实践指南
  • PH热榜 | 2025-05-20
  • springboot框架 集成海康ISUP-SDK 并实现 协议透传给设备下发指令!
  • 武汉科技大学人工智能与演化计算实验室许志伟课题组参加第八届智能优化与调度学术会议
  • 【QT】QTableWidget获取width为100,与真实值不符问题解决
  • BUUCTF——Kookie
  • C语言学习之内存函数
  • Python打卡训练营day27-函数-装饰器
  • 深入解析MATLAB codegen生成MEX文件的原理与优势
  • MySQL高频面试八连问(附场景化解析)
  • 【MySQL】第六弹——表的CRUD进阶(四)聚合查询(下)
  • 【C# 自动化测试】借助js获取浏览器滚动条高度
  • 2025ICPC武汉邀请赛-F
  • 【c# 类型转换中 as 和()】
  • DAY29 超大力王爱学Python
  • Java异常处理与File类终极指南
  • Java高频面试之并发编程-19
  • 【Qt】在OrinNX上,使用命令安装qtmultimedia5-dev时报错
  • 西尔艾力·外力任吐鲁番市副市长、代理市长,朱继坤任副市长
  • 国家能源局:4月份全社会用电量同比增长4.7%
  • 上海浦江游览南拓新航线首航,途经前滩、世博文化公园等景点
  • 央媒聚焦文明交流互鉴中的“上博现象” :跨越山海,抒写自信
  • 国内规模最大女子赛艇官方赛事在沪启航,中外41支队伍逐浪
  • 解锁儿时愿望!潘展乐战胜孙杨,全国冠军赛男子400自夺冠