宏函数返回值(C/C++)

3 篇文章 0 订阅

1 背景

最近开发新模块的驱动,看了下大佬提交的代码(封装给我用),每个寄存器读写通过宏函数封装实现的API。另外,我们的Linux内核中很多的函数也是通过宏函数定义的。按照其格式修改下,大致如下,:

/*寄存器定义*/
typedef struct{
    unsigned int rx_en                                      : 1 ;
    unsigned int a			                                : 1 ;
    unsigned int b			                                : 2 ;
    unsigned int c		                                    : 1 ;
    unsigned int d			                                : 1 ;
    unsigned int e		                                    : 3 ;
    unsigned int f                                          : 7 ;
    unsigned int g	                                        : 14 ;
    unsigned int h		                                    : 2 ;
} __attribute__ ((packed)) Reg_ModuleRxCfg;

/*
*SET_MODULE_RX_ENABLE(_en)  RX使能宏函数写接口
*GET_MODULE_RX_ENABLE()		RX使能宏函数读接口
*MODULE_REG_READ、MODULE_REG_WRITE寄存器读写
*/
#define SET_MODULE_RX_ENABLE(_en)\
    do {Reg_ModuleRxCfg __c = {0};\
        MODULE_REG_READ(MODULE_RX_CFG, (unsigned int *)&__c);\
        __c.rx_en = !!_en;\
        MODULE_REG_WRITE(MODULE_RX_CFG, *((unsigned int *)&__c));\
    }while(0)

#define GET_MODULE_RX_ENABLE()\
    ({  Reg_ModuleRxCfg __c1 = {0}; unsigned int __c;\
        MODULE_REG_READ(MODULE_RX_CFG, (unsigned int *)&__c);\
        memcpy((void*)&__c1, (void*)&__c, sizeof(unsigned int));\
        __c1.rx_en;\
    })

/*
*接口使用
*/
SET_MODULE_RX_ENABLE(1);
unsigned char RxEnable = 0;
RxEnable = GET_MODULE_RX_ENABLE();

接口使用处,写寄存器还好理解,但是读就不好理解了,宏函数返回值是什么

2宏函数返回值

接下来就来一看究竟。
直接仿照写段代码,跑一下:

#include <stdio.h>


#define REGREAD(_DAYOFWEEK_)\
({\
	char* str;\
	switch (_DAYOFWEEK_){\
		case 1:\
		case 2:\
		case 3:\
		case 4:\
		case 5:\
			str = "小伙子,好好上班!";\
			break;\
		case 6:\
		case 7:\
			str = "小伙子,来加个班呀!";\
			break;\
		default:\
			str = "小伙子,今年过年别回家了,加个班吧!";\
	}\
	(str);\
})\

int main() {
	int i;
    char* str;
	for(i = 0; i <= 7; i++){
		str = REGREAD(i);
    	printf("%s\n", str);
	}
    return 0;
}

跑一下:
在这里插入图片描述

从输出可以看出:
宏函数的返回值,即宏函数中最后一个表达式的值;宏函数的返回值的类型,是最后一个表达式的类型。

3 汇编查看

gcc -S macro_return.c -o macro_return.s

	.file	"macro_return.c"
	.text
	.section	.rodata
.LC0:
	.string	"\345\260\217\344\274\231\345\255\220\357\274\214\345\245\275\345\245\275\344\270\212\347\217\255\357\274\201"
	.align 8
.LC1:
	.string	"\345\260\217\344\274\231\345\255\220\357\274\214\346\235\245\345\212\240\344\270\252\347\217\255\345\221\200\357\274\201"
	.align 8
.LC2:
	.string	"\345\260\217\344\274\231\345\255\220\357\274\214\344\273\212\345\271\264\350\277\207\345\271\264\345\210\253\345\233\236\345\256\266\344\272\206,\345\212\240\344\270\252\347\217\255\345\220\247\357\274\201"
	.text
	.globl	main
	.type	main, @function
main:
.LFB0:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	subq	$32, %rsp
	movl	$0, -4(%rbp)
	jmp	.L2
.L7:
	cmpl	$0, -4(%rbp)
	jle	.L3
	cmpl	$5, -4(%rbp)
	jle	.L4
	cmpl	$7, -4(%rbp)
	jg	.L3
	jmp	.L9
.L4:
	movq	$.LC0, -16(%rbp)
	jmp	.L6
.L9:
	movq	$.LC1, -16(%rbp)
	jmp	.L6
.L3:
	movq	$.LC2, -16(%rbp)
.L6:
	movq	-16(%rbp), %rax
	movq	%rax, -24(%rbp)
	movq	-24(%rbp), %rax
	movq	%rax, %rdi
	call	puts
	addl	$1, -4(%rbp)
.L2:
	cmpl	$7, -4(%rbp)
	jle	.L7           /*jle:条件转移指令。小于或等于,或者不大于则转移*/
	movl	$0, %eax
	leave
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE0:
	.size	main, .-main
	.ident	"GCC: (GNU) 8.3.1 20190507 (Red Hat 8.3.1-4)"
	.section	.note.GNU-stack,"",@progbits

有点乱,简单分析下:

  • 1、从main函数开始,进入.L2再到.L7,在.L7中进行for循环和判断
  • 2、.L4、.L9、.L3是switch中对应不同case的标签,可以看出.LC0:、.LC1:、.LC2:中的字符串放到了寄存器-16(%rbp)
  • 3、最后在.L6:中进行处理,并调用了puts函数,将字符串输出。

从汇编也可以看出,输出的是最后一个表达式的值

  • 8
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 C 语言中,lambda 表达式是不支持的。Lambda 表达式是一种匿名函数的形式,通常用于函数式编程语言中。如果你想在 C 语言中实现类似的功能,你可以考虑使用函数指针或来达到类似的效果。 函数指针是指向函数的指针变量,可以用来间接调用函数。它可以在运行时动态指定要调用的函数。你可以定义一个函数指针,并在需要的时候将其赋值给一个具体的函数,然后通过调用函数指针来执行相应的操作。 是一种预处理指令,可以将代码片段替换为指定的内容。你可以定义一个带参数的,在宏定义中指定返回值,并在需要的地方调用该来实现相应的功能。 下面是使用函数指针和实现类似 lambda 表达式的示例: 使用函数指针: ```c #include <stdio.h> int add(int a, int b) { return a + b; } int subtract(int a, int b) { return a - b; } typedef int (*Operation)(int, int); int calculate(Operation op, int a, int b) { return op(a, b); } int main() { Operation addOp = add; Operation subtractOp = subtract; int result1 = calculate(addOp, 5, 3); int result2 = calculate(subtractOp, 5, 3); printf("Addition result: %d\n", result1); printf("Subtraction result: %d\n", result2); return 0; } ``` 使用: ```c #include <stdio.h> #define OPERATION(a, b) ((a) + (b)) int main() { int result = OPERATION(5, 3); printf("Result: %d\n", result); return 0; } ``` 这些示例只是简单地展示了如何在 C 语言中实现类似 lambda 表达式的功能,具体的使用方式可以根据你的需求进行调整和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值