C语言中带返回值的宏定义方式
C语言中带返回值的宏定义
相信大家在实际工作中,一定有遇到需要编写一个宏定义,且希望它能带返回值的场景吧?
比如我之前就遇到一个场景,早期的代码是使用函数实现的功能,现在想换成宏定义,但是又要保留之前调用函数的代码不动,这样我就只能想办法写一个带返回值的宏了。
宏定义编写
直接上demo:
#include <stdio.h> /* always return 1 */ #define RETURN_MACRO() ({do {} while(0);1;}) #define RETURN_MACRO2() 1 /* return a+b */ #define A_PLUS_B_MACRO(a, b) ({int ret; ret = (a) + (b); ret;}) #define A_PLUS_B_MACRO2(a, b) ({int ret; ret = add((a), (b)); ret;}) int add(int a, int b) { return (a + b); } int main(int argc, const char *argv[]) { int a = 6; int b = 7; printf("Hello world !\n"); printf("RETURN_MACRO: %d\n", RETURN_MACRO()); printf("RETURN_MACRO2: %d\n", RETURN_MACRO2()); printf("a + b = %d\n", A_PLUS_B_MACRO(a, b)); printf("a + b = %d\n", A_PLUS_B_MACRO2(a, b)); return 0; }
宏定义分析
为了分析宏定义的写法,我们得知道宏定义最终被展开是什么样的。
我在之前的博文中有提到,使用gcc编译器的话,可以在CFLAGS上加上-save-temps=obj这个编译选项,这样就可以得到预编译处理之后的文件,后缀名是.i。
我们使用编译脚本编译之后,得到.i文件如下:
//前面的内容忽略 # 3 "main.c" 2 # 12 "main.c" # 12 "main.c" int add(int a, int b) { return (a + b); } int main(int argc, const char *argv[]) { int a = 6; int b = 7; printf("Hello world !\n"); printf("RETURN_MACRO: %d\n", ({do {} while(0);1;})); printf("RETURN_MACRO2: %d\n", 1); printf("a + b = %d\n", ({int ret; ret = (a) + (b); ret;})); printf("a + b = %d\n", ({int ret; ret = add((a), (b)); ret;})); return 0; }
从.i文件我们可以看到,宏定义被正常展开,下面确认下功能是否正常。
宏定义验证
我们执行编译出来的可执行文件:
return_macro$ ./test Hello world ! RETURN_MACRO: 1 RETURN_MACRO2: 1 a + b = 13 a + b = 13
验证成功。
经验总结
- 在C语言里面,可以使用({aaa; bbb; ccc;})来实现宏定义带返回值;这里的返回值是最后一个;的值。
- 注意里面的()和{}都不能少,否则可能会破坏代码的语法结构,导致得不到正确的答案。
C语言中一些宏定义和常用的函数
typeof 关键字
如果你是 C++ 程序员,应该接触过 C++11 里的 decltype 操作符,它的作用是自动推导表达式的数据类型,以解决泛型编程中有些类型由模板参数决定而难以(甚至不可能)表示的问题。
其实这个特性在 C 语言中也早有类似的实现,GNU C 标准中的一个扩展特性 typeof 作用与 decltype 类似。
__typeof__ (ret) errnum = (ret);
snprintf()函数的作用
#include<stdio.h> int snprintf(char* dest_str,size_t size,const char* format,...);
【函数功能】:
先将可变参数 “…” 按照format的格式格式化为字符串,然后再将其拷贝至dest_str中。
如果格式化后的字符串长度小于size,则将字符串全部拷贝至dest_str中,并在字符串结尾处加上‘\0’; 如果格式化后的字符串长度大于或等于size,则将字符串的(size-1)拷贝至dest_str中,然后在字符串结尾处加上’\0’. 函数返回值是 格式化字符串的长度。
__builtin_expect的作用
__builtin_expect(errnum != 0, 0)
这个指令是gcc引入的,作用是"允许程序员将最有可能执行的分支告诉编译器"。
这个指令的写法为:__builtin_expect(EXP, N)。意思是:EXP==N的概率很大。
一般的使用方法是将__builtin_expect指令封装为LIKELY和UNLIKELY宏。
C语言中常用的预定义
__LINE__
:当前程序行的行号,表示为十进制整型常量__FILE__
:当前源文件名,表示字符串型常量__DATE__
:转换的日历日期,表示为Mmm dd yyyy 形式的字符串常量,Mmm是由asctime产生的。__TIME__
:转换的时间,表示"hh:mm:ss"形式的字符串型常量,是有asctime产生的。(asctime貌似是指的一个函数)__STDC__
:编辑器为ISO兼容实现时位十进制整型常量__func__
:它指示所在的函数__assert_perror_fail
:打印一条包含错误码ERRNUM的错误消息,并终止程序
反斜杠的作用
反斜杠起到换行作用,用于宏定义和字符串换行。其中宏定义中使用居多。
如果一行代码有很多元素,导致太长影响阅读,可以通过在结尾加\的方式,实现换行,编译时会忽略\及其后的换行符,当做一行处理。
#define CHECK_ACTION_RETURN(expr) \ if (!expr) { \ printf(":failed(%d)\n", ret); \ return ret; \ } else { \ printf(":ok\n"); \ }
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持猪先飞。
原文出处:https://blog.csdn.net/szullc/article/details/121297749
相关文章
- 这篇文章主要为大家详细介绍了C语言实现放烟花的程序,有音乐播放,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-02-23
- 这篇文章主要介绍了详解如何将c语言文件打包成exe可执行程序,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-02-25
- 这篇文章主要介绍了C语言中求和、计算平均值、方差和标准差的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-12-10
- 这篇文章主要介绍了Java List集合返回值去掉中括号('[ ]')的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-08-29
- 这篇文章主要介绍了Feign接口方法返回值设置方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-07-08
- 今天小编就为大家分享一篇C语言实现从文件读入一个3*3数组,并计算每行的平均值,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-04-25
- 这篇文章主要对C语言中const关键字的用法进行了详细的分析介绍,需要的朋友可以参考下...2020-04-25
- 这篇文章主要为大家详细介绍了C语言单链表实现多项式相加,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-04-25
- 这篇文章主要介绍了C语言简单实现计算字符个数的方法,涉及C语言针对字符串的简单遍历与判定技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-04-25
- 对数组进行操作,查找、插入、删除...2020-04-25
- 本文给大家简单介绍下c实现linux下的数据库备份的方法和具体的源码,十分的实用,有需要的小伙伴可以参考下。...2020-04-25
- 这里给大家分享的是一个使用C语言实现的判断字符串中是否以某字符开头或者结尾的代码,非常的简单实用,希望大家能够喜欢...2020-04-25
- 这篇文章主要介绍了C语言循环结构与时间函数用法,是C语言中非常重要的一个技巧,需要的朋友可以参考下...2020-04-25
- 这篇文章主要介绍了C语言/C++如何生成随机数,C语言/C++产生随机数主要用到的是rand()函数, srand()函数,C语言/C++里没有自带的random(int number)函数,如何解决?感兴趣的小伙伴们可以参考一下...2020-04-25
- free函数是释放之前某一次malloc函数申请的空间,而且只是释放空间,并不改变指针的值。下面我们就来详细探讨下...2020-04-25
- 这篇文章主要为大家详细介绍了C语言学生成绩管理系统小设计,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-04-25
- 这篇文章主要介绍了C语言中逻辑运算符与条件运算符的学习教程,条件运算符问号即三目运算符使用起来十分方便,需要的朋友可以参考下...2020-04-25
- 这篇文章主要介绍了C语言入门之基础知识详解,文中有非常详细的C语言使用教程及相关基础知识,对正在学习c语言的小伙伴们有非常好的帮助,需要的朋友可以参考下...2021-08-04
- 这篇文章主要为大家详细介绍了C语言实现简单的贪吃蛇游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-07-28
- 这篇文章主要为大家详细介绍了C语言版五子棋游戏的实现代码,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-07-29