c语言宏定义唯一匿名变量,C语言宏定义技巧

2023-11-08

写好C语言,漂亮的宏定义很重要,使用宏定义可以防止出错,提高可移植性,可读性,方便性 等等。下面列举一些成熟软件中常用得宏定义。。。。。。

1、防止一个头文件被重复包含

#ifndef COMDEF_H

#define COMDEF_H

//头文件内容

#endif

2、重新定义一些类型,防止由于各种平台和编译器的不同,而产生的类型字节数差异,方便移植。

typedef unsigned char boolean; /* Boolean value type. */

typedef unsigned long int uint32; /* Unsigned 32 bit value */

typedef unsigned short uint16; /* Unsigned 16 bit value */

typedef unsigned char uint8; /* Unsigned 8 bit value */

typedef signed long int int32; /* Signed 32 bit value */

typedef signed short int16; /* Signed 16 bit value */

typedef signed char int8; /* Signed 8 bit value */

//下面的不建议使用

typedef unsigned char byte; /* Unsigned 8 bit value type. */

typedef unsigned short word; /* Unsinged 16 bit value type. */

typedef unsigned long dword; /* Unsigned 32 bit value type. */

typedef unsigned char uint1; /* Unsigned 8 bit value type. */

typedef unsigned short uint2; /* Unsigned 16 bit value type. */

typedef unsigned long uint4; /* Unsigned 32 bit value type. */

typedef signed char int1; /* Signed 8 bit value type. */

typedef signed short int2; /* Signed 16 bit value type. */

typedef long int int4; /* Signed 32 bit value type. */

typedef signed long sint31; /* Signed 32 bit value */

typedef signed short sint15; /* Signed 16 bit value */

typedef signed char sint7; /* Signed 8 bit value */

3,得到指定地址上的一个字节或字

#define MEM_B( x ) ( *( (byte *) (x) ) )

#define MEM_W( x ) ( *( (word *) (x) ) )

4,求最大值和最小值

#define MAX( x, y ) ( ((x) > (y)) ? (x) : (y) )

#define MIN( x, y ) ( ((x) < (y)) ? (x) : (y) )

5,得到一个field在结构体(struct)中的偏移量

#define FPOS( type, field ) \

/*lint -e545 */ ( (dword) &(( type *) 0)-> field ) /*lint +e545 */

6,得到一个结构体中field所占用的字节数

#define FSIZ( type, field ) sizeof( ((type *) 0)->field )

7,按照LSB格式把两个字节转化为一个Word

#define FLIPW( ray ) ( (((word) (ray)[0]) * 256) + (ray)[1] )

8,按照LSB格式把一个Word转化为两个字节

#define FLOPW( ray, val ) \

(ray)[0] = ((val) / 256); \

(ray)[1] = ((val) & 0xFF)

9,得到一个变量的地址(word宽度)

#define B_PTR( var ) ( (byte *) (void *) &(var) )

#define W_PTR( var ) ( (word *) (void *) &(var) )

10,得到一个字的高位和低位字节

#define WORD_LO(xxx) ((byte) ((word)(xxx) & 255))

#define WORD_HI(xxx) ((byte) ((word)(xxx) >> 8))

11,返回一个比X大的最接近的8的倍数

#define RND8( x ) ((((x) + 7) / 8 ) * 8 )

12,将一个字母转换为大写

#define UPCASE( c ) ( ((c) >= 'a' && (c) <= 'z') ? ((c) - 0x20) : (c) )

13,判断字符是不是10进值的数字

#define DECCHK( c ) ((c) >= '0' && (c) <= '9')

14,判断字符是不是16进值的数字

#define HEXCHK( c ) ( ((c) >= '0' && (c) <= '9') ||\

((c) >= 'A' && (c) <= 'F') ||\

((c) >= 'a' && (c) <= 'f') )

15,防止溢出的一个方法

#define INC_SAT( val ) (val = ((val)+1 > (val)) ? (val)+1 : (val))

16,返回数组元素的个数

#define ARR_SIZE( a ) ( sizeof( (a) ) / sizeof( (a[0]) ) )

17,返回一个无符号数n尾的值MOD_BY_POWER_OF_TWO(X,n)=X%(2^n)

#define MOD_BY_POWER_OF_TWO( val, mod_by ) \

( (dword)(val) & (dword)((mod_by)-1) )

18,对于IO空间映射在存储空间的结构,输入输出处理

#define inp(port) (*((volatile byte *) (port)))

#define inpw(port) (*((volatile word *) (port)))

#define inpdw(port) (*((volatile dword *)(port)))

#define outp(port, val) (*((volatile byte *) (port)) = ((byte) (val)))

#define outpw(port, val) (*((volatile word *) (port)) = ((word) (val)))

#define outpdw(port, val) (*((volatile dword *) (port)) = ((dword) (val)))

[2005-9-9添加]

19,使用一些宏跟踪调试

A N S I标准说明了五个预定义的宏名。它们是:

_ L I N E _

_ F I L E _

_ D A T E _

_ T I M E _

_ S T D C _

如果编译不是标准的,则可能仅支持以上宏名中的几个,或根本不支持。记住编译程序

也许还提供其它预定义的宏名。

_ L I N E _及_ F I L E _宏指令在有关# l i n e的部分中已讨论,这里讨论其余的宏名。

_ D AT E _宏指令含有形式为月/日/年的串,表示源文件被翻译到代码时的日期。

源代码翻译到目标代码的时间作为串包含在_ T I M E _中。串形式为时:分:秒。

如果实现是标准的,则宏_ S T D C _含有十进制常量1。如果它含有任何其它数,则实现是

非标准的。

可以定义宏,例如:

当定义了_DEBUG,输出数据信息和所在文件所在行

#ifdef _DEBUG

#define DEBUGMSG(msg,date) printf(msg);printf(“%d%d%d”,date,_LINE_,_FILE_)

#else

#define DEBUGMSG(msg,date)

#endif

20,宏定义防止使用是错误

用小括号包含。

例如:#define ADD(a,b) (a+b)

用do{}while(0)语句包含多语句防止错误

例如:#difne DO(a,b) a+b;\

a++;

应用时:if(….)

DO(a,b); //产生错误

else

解决方法: #difne DO(a,b) do{a+b;\

a++;}while(0)

宏中"#"和"##"的用法

一、一般用法

我们使用#把宏参数变为一个字符串,用##把两个宏参数贴合在一起.

用法:

#i nclude

#i nclude

using namespace std;

#define STR(s) #s

#define CONS(a,b) int(a##e##b)

int main()

{

printf(STR(vck)); // 输出字符串"vck"

printf("%d\n", CONS(2,3)); // 2e3 输出:2000

return 0;

}

二、当宏参数是另一个宏的时候需要注意的是凡宏定义里有用'#'或'##'的地方宏参数是不会再展开.

1, 非'#'和'##'的情况

#define TOW (2)

#define MUL(a,b) (a*b)

printf("%d*%d=%d\n", TOW, TOW, MUL(TOW,TOW));

这行的宏会被展开为:

printf("%d*%d=%d\n", (2), (2), ((2)*(2)));

MUL里的参数TOW会被展开为(2).

2, 当有'#'或'##'的时候

#define A (2)

#define STR(s) #s

#define CONS(a,b) int(a##e##b)

printf("int max: %s\n", STR(INT_MAX)); // INT_MAX #i nclude

这行会被展开为:

printf("int max: %s\n", "INT_MAX");

printf("%s\n", CONS(A, A)); // compile error

这一行则是:

printf("%s\n", int(AeA));

INT_MAX和A都不会再被展开, 然而解决这个问题的方法很简单. 加多一层中间转换宏.

加这层宏的用意是把所有宏的参数在这层里全部展开, 那么在转换宏里的那一个宏(_STR)就能得到正确的宏参数.

#define A (2)

#define _STR(s) #s

#define STR(s) _STR(s) // 转换宏

#define _CONS(a,b) int(a##e##b)

#define CONS(a,b) _CONS(a,b) // 转换宏

printf("int max: %s\n", STR(INT_MAX)); // INT_MAX,int型的最大值,为一个变量 #i nclude

输出为: int max: 0x7fffffff

STR(INT_MAX) --> _STR(0x7fffffff) 然后再转换成字符串;

printf("%d\n", CONS(A, A));

输出为:200

CONS(A, A) --> _CONS((2), (2)) --> int((2)e(2))

三、'#'和'##'的一些应用特例

1、合并匿名变量名

#define ___ANONYMOUS1(type, var, line) type var##line

#define __ANONYMOUS0(type, line) ___ANONYMOUS1(type, _anonymous, line)

#define ANONYMOUS(type) __ANONYMOUS0(type, __LINE__)

例:ANONYMOUS(static int); 即: static int _anonymous70; 70表示该行行号;

第一层:ANONYMOUS(static int); --> __ANONYMOUS0(static int, __LINE__);

第二层: --> ___ANONYMOUS1(static int, _anonymous, 70);

第三层: --> static int _anonymous70;

即每次只能解开当前层的宏,所以__LINE__在第二层才能被解开;

2、填充结构

#define FILL(a) {a, #a}

enum IDD{OPEN, CLOSE};

typedef struct MSG{

IDD id;

const char * msg;

}MSG;

MSG _msg[] = {FILL(OPEN), FILL(CLOSE)};

相当于:

MSG _msg[] = {{OPEN, "OPEN"},

{CLOSE, "CLOSE"}};

3、记录文件名

#define _GET_FILE_NAME(f) #f

#define GET_FILE_NAME(f) _GET_FILE_NAME(f)

static char FILE_NAME[] = GET_FILE_NAME(__FILE__);

4、得到一个数值类型所对应的字符串缓冲大小

#define _TYPE_BUF_SIZE(type) sizeof #type

#define TYPE_BUF_SIZE(type) _TYPE_BUF_SIZE(type)

char buf[TYPE_BUF_SIZE(INT_MAX)];

--> char buf[_TYPE_BUF_SIZE(0x7fffffff)];

--> char buf[sizeof "0x7fffffff"];

这里相当于:

char buf[11];

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

c语言宏定义唯一匿名变量,C语言宏定义技巧 的相关文章

  • Java 判断一个对象中某一个属性的值是否为空

    每次写博客都不知道咋开头 算了 直接说问题吧 就是验证一个对象中的一个属性的值是否为空 自己在网上也找到了很多大神给的答案 有看到利用反射机制 public boolean checkObjFieldIsNull Object obj th
  • react 获取response header中content-disposition中的filename值

    我们在开发中经常会碰到下载文件 后端将fileName放在response header中 我们该如何获取呢 首先是请求接口 注 getResponse true 这个属性必不可少 它可以返回返回 data response 其次是代码写法
  • 不识别v-on标签,不识别v-bind标签 idea 报错(Namespace 'v-on' not bound more....)

    解决办法 setting 里面去掉这个UNbound xml namespace prefix
  • python去掉字符串重复字符_【python】【字符串】字符串首尾相连,去掉连接处的重复...

    coding utf 8 字符串从反向拆词 def string depart str1 ls str1 str tmp for str t in reversed str1 str tmp str t str tmp ls str1 ap
  • 通信技术之复用与解复用

    想像一下 如果一条信道一次只能传输一条信息 那么对于海量的信息来说 传输的速度未免太慢了 因此 我们想要一根线上传送多路信号 复用技术就应运而生了 在上一篇博客中 我们知道了PCM编码的位数是8 抽样周期是1s 8000次 125us 在这
  • 机器学习——基本认识

    一 机器学习定义 机器学习 Machine Learning 什么是机器学习 Arthur Samuel 机器学习领域的先驱之一 他编写了世界上第一个棋类游戏的人工智能程序 1959年对机器学习的定义 Machine Learning is
  • Fiddler Everywhere(TTP调试抓包工具) for Mac苹果电脑版

    Fiddler Everywhere for Mac版是Mac电脑上的一款跨平台的HTTP调试抓包工具 Fiddler Everywhere for Mac能够记录客户端与服务器之间的所有HTTP S 通信 支持对包进行监视 分析 设置断点
  • 微信小程序——小程序的API介绍

    小程序的宿主环境 API 1 小程序API概述 小程序中的API是由宿主环境提供的 通过这些丰富的小程序API 开发者可以方便的调用微信提供的能力 例如 获取用户信息 本地存储 支付功能等 2 小程序API的3大分类 小程序官方把API分成
  • 用户行为记录的一个简单例子

    分析的前提 用户行为分析的前提是用户行为的记录 如下图则记录了三个用户的用户记录 设计用户记录 用户记录都包含哪些呢 用户记录对于数据分析非常重要 可以让程序员定位bug或者性能问题 产品可以查看用户体验 甚至是广告分析数据分析和用户增长模
  • 算法学习:55. 跳跃游戏

    跳跃游戏 题目难度 中等 给定一个非负整数数组 nums 你最初位于数组的 第一个下标 数组中的每个元素代表你在该位置可以跳跃的最大长度 判断你是否能够到达最后一个下标 示例 输入 nums 2 3 1 1 4 输出 true 解释 可以先
  • Iterm2设置

    Item2 1 安装item2 使用 homebrew 安装 item2 brew install item2 可以打开 item2了使用了 查看所有 shell cat etc shells 查看当前 shell echo SHELL 切
  • RK3568平台入门到精通系列讲解之开发环境搭建(依赖软件包)

    一 服务器平台信息 芯片平台 Intel至强E526xx系列x2 系统版本 ubuntu 14 04 18 04 22 04服务器版 内存 128GB 磁盘空间 256GB SSD 8TB HD 二 服务器系统安装 系统可以从官方下载 ht
  • 常用Linux网络/内存/磁盘分析工具

    Centos查看网卡 CPU 内存等使用率 watch more proc net dev 性能分析和监控工具 uptime dmesg tail vmstat 1 mpstat P ALL 1 pidstat 1 iostat xz 1
  • Freesync小白科普

    内容摘自AMD官网 AMD FreeSync 技术解释 FreeSync是一项 AMD 计划 它利用 DisplayPort Adaptive Sync 等行业标准为最终用户提供动态刷新率 与G sync一样 可以解决画面卡顿 撕裂问题 作
  • [Markdown][typora]如何让markdown自动显示序号

    介绍 我们经常会遇到在写markdown的时候 需要显示标题 这个时候 通常大家的做法是手动添加标题 但是写到最后会发现要在添加一个之前的章节 结果后面的写好的都要跟着改 那markdown有没有办法自动显示标题呢 这边我搜索了相关博客 学
  • 自带字典_原来华为手机还自带在线翻译功能,无需任何软件,即可随时翻译!...

    翻译大家都并不陌生 就算在我们生活中都可能会用上 那更别提学习或工作中了 以前我们翻译英文都会使用英汉字典 但是随着现在科技的发展现在我们手机上都会自带一些翻译软件 就比如我们国产华为手机 如果你能够合理化的利用必定能够让你事半功倍 一 手
  • 【论文研读】【医学图像】【R2UNet】Recurrent residual U-Net for medical image segmentation

    R2UNet Recurrent residual U Net for medical image segmentation Abstract 1 Introduction 2 Related Works 3 RU Net and R2U
  • jieba自定义分词规则与多进程切词

    当存在某些自定义的专业名称或长词时 jieba有可能会当成多个词 但其实是一个词 自定义的方法如下 原始的jieba效果 import jieba if name main sentence 学习python与人工智能有益身体健康 ret
  • ubuntu常用命令(转载)

    ls 列出当前目录文件 不包括隐含文件 ls a 列出当前目录文件 包括隐含文件 ls l 列出当前目录下文件的详细信息 cd 回当前目录的上一级目录 cd 回上一次所在的目录 cd 或 cd 回当前用户的宿主目录 mkdir 目录名 创建

随机推荐

  • ide运行报错“Command line is too long”解决办法

    有时运行程序时 ide会报如下错 如何解决呢 其实提示已经告诉你解决办法了 点击图中的蓝色超链接 JAR MAINIFEST 或 CLASSPATH FILE 都能解决问题 这是因为命名的方法名太长了才会报这个错 方法2 如果没有弹窗 也可
  • 查看Linux下rpm文件安装到哪个路径

    命令 root localhost rpm qpl xxx rpm more
  • 用户数据报UDP

    UDP概述 UDP 只在 IP 的数据报服务之上增加了很少一点的功能 即端口的功能和差错检测的功能 UDP 的主要特点 UDP 是无连接的 不需要建立连接 直接发送数据 发送完以后也不需要释放连接 UDP 使用尽最大努力交付 即不保证可靠交
  • 使用 MATLAB 绘制爱心:帮助你成功表白

    作者简介 人工智能专业本科在读 喜欢计算机与编程 写博客记录自己的学习历程 个人主页 小嗷犬的个人主页 个人网站 小嗷犬的技术小站 个人信条 为天地立心 为生民立命 为往圣继绝学 为万世开太平 本文目录 MATLAB 绘制爱心 方法一 方法
  • C++中string的size与length的区别

    在C 的string类中 有两种函数 length和size 他们的作用都是返回字符串的长度 那么 问题来了 他们两者有什么区别 为了钻研 我们要先找到他们两者的源代码 让我们先找到length的源代码 首先 我们随便定义一个字符串 并调用
  • hualinux dj3 2.4:drf普通视图generics及例子

    目录 一 关于通用视图generics 1 1 基于类的视图 1 2 关于通用视图 1 2 1 介绍 1 2 2 属性 1 2 3 方法 1 2 4 Mixins 1 2 5 具体的通用视图 1 2 6 其它 二 drf通用视图generi
  • 内核调试手段

    1 内核调试配置选项 内核拥有多项用于调试的功能 但是这些功能会造成额外的输出并导致性能下降 因此 内核通常都是禁止掉调试功能 内核调试相关的配置项主要集中在内核配置菜单 Kernel hacking 中 在使用下面的调试手段时 先确保内核
  • 如何修改unity项目名称

    在Unity中 修改项目名称需要对一些文件和设置进行修改 以下是修改Unity项目名称的步骤 在Unity编辑器中 选择项目文件夹 Project 面板中的 Assets 然后点击右键 在弹出菜单中选择 Show in Explorer 在
  • 项目管理利器—maven

    一 简介 maven是优秀的项目管理和构建工具 能让我们更为方便的来管理和构建项目 从最基础的环境配置 到maven核心知识点的应用 使用maven来构建和管理Java项目 Maven是基于项目对象模型 POM 可以通过一小段描述信息来管理
  • JavaScript数组中筛选相同的元素组成新数组

    var college type 2 lastName 孙策 type 1 lastName 后裔 type 3 lastName 阿木木 type 3 lastName 亚索 type 1 lastName 剑魔 type 1 lastN
  • 写给我的2015—开启工作新旅程

    前沿 2015年的总结相比2014年来的晚了许多 原因一方面是今年呀的发现CSDN竟然没有了前两年写年终的活动 另一方面嘛还是自己太懒散了 一直恍恍惚惚的没有下手来总结 今天 在这小年夜里 ps 外面下完雪挺冷的 独自一个人坐在办公桌前 静
  • 实心球体内部电势计算公式_均匀带电球体中心点电势怎么求

    展开全部 公式 q 其中 为电势能 q为电荷量 为电势 即 q 均匀带电球内的电场分布和距离球心的距32313133353236313431303231363533e4b893e5b19e31333431363565离r成正比 解析 由于正
  • linux文件权限查看及修改-chmod ------入门的一些常识

    查看linux文件的权限 ls l 文件名称ULUitugULUitug查看linux文件夹的权限 ls ld 文件夹名称 所在目录 ULUitugULUitug修改文件及文件夹权限 ULUitugULUitugsudo chmod 代表类
  • 【软件工程】内聚

    概念 是指一个模块内部个成分之间相互关联程度的度量 也就是说 凝聚是对模块内各处理动作组合强度的一种度量 很显然 一个模块的内聚越大越好 偶然凝聚 一个模块内的各处理元素之间没有任何联系 只是偶然地被凑到一起 这种模块也称为巧合内聚 内聚程
  • MySQL数据库引擎InnoDB和MyISAM的区别?

    数据库引擎InnoDB和MyISAM的区别 1 MyISAM不支持事务 InnoDB支持事务 2 MyISAM支持全文索引 InnoDB在MySQL5 6之前不支持 3 MyISAM不支持外键 InnoDB支持外键 4 MyISAM只支持表
  • STM32之flash的读写

    本文内容 本实验主要介绍Flash地址空间的数据读取 一 创建STM32CUBEMX工程 芯片选择F103C8 配置定时器 打开外部时钟 配置时钟 配置PC13为output对应板子上的LED 设置堆栈大小为4K 导出 二 KEIL下的配置
  • Vue 3 第七章:computed计算属性

    文章目录 1 Vue3中的computed函数 1 1 什么是computed 1 2 如何定义computed 1 3 computed函数的使用场景 1 3 1 过滤和排序 1 3 1 数组计算 2 computed函数的原理 总结 1
  • getset_descriptor

    What is the dict dict attribute of a Python class up vote 43 down vote favorite 23 gt gt gt class A object pass gt gt gt
  • 第六章 Hystrix断路器详解+环境搭建

    目录 一 Hystrix的背景及介绍 1 分布式系统面临的问题 2 解决方案 3 Hystrix介绍 4 Hystrix服务熔断 二 搭建项目基础环境 1 创建 父工程及公共api 见 第三章 2 创建 Eureka 服务 见 第三章 3
  • c语言宏定义唯一匿名变量,C语言宏定义技巧

    写好C语言 漂亮的宏定义很重要 使用宏定义可以防止出错 提高可移植性 可读性 方便性 等等 下面列举一些成熟软件中常用得宏定义 1 防止一个头文件被重复包含 ifndef COMDEF H define COMDEF H 头文件内容 end