C/C++ 宏操作小技巧
Abstract
之前写了一个非常mini的log库(也不算库把,自己瞎jb写的),里面几乎都是宏的实现。这里打算趁热打铁,把自己知道的几下子都贴出来,后续如果有新的收获会更新这个博文。
文笔拙劣,主要是给自己做个提醒。
1. 运行时检测大小端
一目了然,不做解释。
#define __ENDIAN() ({ \
short _a = 0x1234; \
*((char*)&_a) == 0x12 ? 1 : 0; \
})
#define big_endian() (__ENDIAN() == 1)
#define little_endian() (__ENDIAN() == 0)
当然还有另一种方式去确定字节序。下面是编译时确定字节序的方式。
只要通过引入头文件<endian.h>便可以在编译时通过宏判断字节序了。参考 ‘/usr/include/linux/tcp.h’ 你会发现另一种写法(自己去看下)。
#if __BYTE_ORDER == __LITTLE_ENDIAN
// do_sth();
#elif __BYTE_ORDER == __BIG_ENDIAN
// do_sth();
#else
#error "Unknown byte order"
#endif
2. max函数与min函数
max与min函数是最常用的。我们可以有很多方式去实现它,宏,inline,函数等。
由于这两个函数都很小,一般不建议
#define max(a, b) ({ \
typeof(a) _a = a; \
typeof(b) _b = b; \
_a >= _b ? _a : _b; \
})
3. SDK 中的函数名拼接
#include <stdio.h> #define test(__DOC, args) __SDK_##__DOC##_TEST(args)
void __SDK_V1_TEST(int a) {
fprintf (stdout, "version %d\n", a);
return;
} void __SDK_V2_TEST(int a) {
fprintf (stdout, "version %d\n", a);
return;
} int main(int argc, char **argv) {
test(V1, 1);
test(V2, 2);
return 0;
}
4. 获取枚举变量的名字
枚举定义通常具有更好的可读性, 比如
enum enWeek_t {MONDAY, TUESDAY};
中MONDAY与TUSDAY比枚举值0,1有更好的可读性。事实上对于开发者,一个可读性更好的名称比这个名称的实际值加友好。如果是日志上能给出‘MONDAY’而不是 0这样的字眼,更能帮助我们理解。所以获取枚举类型的名称或许是个更好的选择。
一个示例:
enum_name.h
#ifndef __ENUM_NAME_H__
#define __ENUM_NAME_H__ // MACRO_HELPER
#define MACRO_HELPER(v) v, #define WEEKDAYS \
MACRO_HELPER(MONDAY)
MACRO_HELPER(TUESDAY)
MACRO_HELPER(WEDNESDAY) // 这里宏替换会换成 enum {MONDAY, TUESDAY, WEDNESDAY,};
enum {
WEEKDAYS
};
16 #undef MACRO_HELPER(v)
#endif //__ENUM_NAME_H__
enum_name.c
#include "enum_name.h" // 这里重新定义宏,利用编译器的特性 #v会把v原封不动的保存为一个字符串类型(## 两个#才是拼接,参考上一篇log函数的实现)
#define MACRO_HELPER(v) {v, #v},
struct week_name_t {
int val;
const char *name;
}; // 结构体的定义中成员顺序,必须和宏的定义一致 // 这里宏会替换成 struct week_names[] = {
// {MONDAY, "MONDAY"}, {TUESDAY, "TUESDAY"}, {WEDNESDAY, "WEDNESDAY"}, {0, 0}}
struct week_names[] = {
WEEKDAYS
{, } // this is the end of array
}; const char *get_enum_name(int v) {
int idx = ;
while (week_names[idx].name) {
if (idx == v)
return week_names[idx].name;
}
return "Unknow";
}
这里我们对外的唯一接口就是 get_enum_name 这个函数,只需要传入指定的数值,我们就能获得对应星期的名字。主要依赖宏替换的效果,如果想追加‘星期四’, ‘星期五’,我们只需要在头文件的 WEEKDAYS 添加 MACRO_HELPER(THURSDAY) 与 MACRO_HELPER(FRIDAY) 就行了,不要要其他的变动。接下来可以写个main函数测试下效果,我就不写了,只是抛砖引玉下。
当然你也可以编写一个函数把所有星期的名称字符串对应输出,这是你的自由,不在这个博问的讨论范围。
C/C++ 宏操作小技巧的更多相关文章
- OMG,12 个精致的 Java 字符串操作小技巧,学它
字符串可以说是 Java 中最具有代表性的类了,似乎没有之一哈,这就好像直播界的李佳琪,脱口秀中的李诞,一等一的大哥地位.不得不承认,最近吐槽大会刷多了,脑子里全是那些段子,写文章都有点不由自主,真的 ...
- VIM的一些操作小技巧
vim的设计理念是:组合. 命令的组合,模式的组合, 普通模式 左: h 上:k 下:j 右 : l i : 当前光标处插入 I: 到光标所在行的行首进入插入模式 a: 在当前光标的后一位 ...
- mysql避免数据库误操作小技巧(转)
避免混淆开发环境的DB和生产环境的DB这在小公司小团队尤其常见.一个人即负责开发,又管DB.桌面上开了一坨终端,有的是开发的DB,有的是生产的DB.一不留神,就写串了,或者粘贴串了.更郁闷的是,有时候 ...
- mac文本操作小技巧——2019年10月17日
声明:看的别人博主写的,自己整理的,非原创,只是自用. mac文本操作技巧 官方指导文档:https://support.apple.com/zh-cn/HT201236 1.光标移动 1.1 行首. ...
- Windows 操作小技巧 之一(持续更新)
1.图片批量旋转 通常携带单反去景点排了大量照片回来处理图片时都会遇到很多横竖杂乱排序的图片难以处理的情形.现提供如下技巧进行处理. 1).在文件夹中添加"方向"的排列或分组选项: ...
- My操作小技巧
1.当我们新增一条数据之后想要获取其自增长的id,可以紧随新增语句后调用 SELECT last_insert_id();即可获得,一般搭配变量一起使用 SELECT @newUserId:=last ...
- Intellij IDEA的一些操作小技巧
1.Presentation Mode 我们可以使用 Presentation Mode,将IDEA弄到最大,可以让你只关注一个类里面的代码,进行毫无干扰的 coding.可以使用Alt+v快捷键,弹 ...
- Unity操作小技巧
1.操作类 1)F:选择物体后聚焦 2)V:选择物体的顶点,顶点吸附 3)Ctrl:摁住后拖动物体,可以按照系统设置的步长进行移动(Edit -> Snap setting) 4)Q W E R ...
- ORCAD中的一些操作小技巧
1.ORCAD中改变元器件和文本字体颜色的命令: 打开在 View -> Toolbar -> Command Window.然后圈选文字(可复选),然后到 Command Window ...
随机推荐
- 洛谷P1308.统计单词数(字符串匹配)
题目描述 一般的文本编辑器都有查找单词的功能,该功能可以快速定位特定单词在文章中的位置,有的还能统计出特定单词在文章中出现的次数. 现在,请你编程实现这一功能,具体要求是:给定一个单词,请你输出它在给 ...
- python关于函数调用作为参数的说明&&装饰器
python关于函数调用作为参数的说明&&装饰器 简单的: 先看代码: def out(): print('out') def inner(): return 'inner' retu ...
- 编写有提示的listbox控件 2008-06-29 17:13
在MFC中几乎所有的控件都有信息提示,而惟有listbox却没有这样的一个功能,每当我们把鼠标移到listbox上控件时,啥玩意儿都没有是不是很气馁啊,所以我今天特地写了一个简单的有提示的listbo ...
- 计算机网络要点---TCP
计算机网络要点---TCP 浏览器在通过域名通过dns服务器找到你的服务器外网ip,将http请求发送到你的服务器,在tcp3次握手之后(http下面是tcp/ip),通过tcp协议开始传输数据,你的 ...
- windows 下 安装 RabbitMQ
RabbitMQ是一个在AMQP协议标准基础上完整的.可复用的企业消息系统.它遵循Mozilla Public License开源协议,采用 Erlang 实现的工业级的消息队列(MQ)服务器.它扮演 ...
- ElasticSearch实战系列七: Logstash实战使用-图文讲解
前言 在上一篇中我们介绍了Logstash快速入门,本文主要介绍的是ELK日志系统中的Logstash的实战使用.实战使用我打算从以下的几个场景来进行讲解. 时区问题解决方案 在我们使用logstas ...
- setjmp()/longjmp()的使用方法
setjmp和longjmp.为了让你实现复杂的流控制,程序在系统里面运行完全依靠内存(代码段,全局段,堆存储器,栈存储器)和寄存器的内容(栈指针,基地址,计数器),setjmp保存当前的寄存器里面的 ...
- 虚拟化技术之kvm磁盘管理工具qemu-img
在前边的博客中,我们大致了解了virsh这个工具对kvm虚拟机的一些操作,回顾请参考https://www.cnblogs.com/qiuhom-1874/tag/virsh/:今天我们来了解下kvm ...
- MySQL数据库时间字段按年月日显示并多字段去重查询
应用服务长久运行,难免要导出一些统计报表. 现在有一个日志表,记录了各种日志,需要导出十月份的登录日志,要求时间按日期显示,且每天用户登陆要去重. 先看日志表的字段构成: logType等于2的是登陆 ...
- 操作系统-I/O(6)I/O与系统调用
所有高级语言的运行时(runtime)都提供了执行I/O功能的机制. 例如,C语言中提供了包含像printf()和scanf()等这样的标准I/O库函数, C++语言中提供了如 <<和&g ...