通过预编译指令实现C语言函数的多返回值

众所周知,C语言里头的函数是只能有一个返回值的。不过我们可以自己写一个头文件,实现C函数的多返回值。

成品大概是这样一个效果:

#include <stdio.h>
#include "return.h"    //    我们将要自定义的文件

mul func(input1, input2, ...){
    ......
    remul(with output1, with output2, ...);    //remul == return multiple
}

int main(){
    ......
    from func(input1, input2, ...) to (val1, type) to (val2, type) to ...;
    ......
}

下面我大致地演示一下具体实现过程:

        假如我们现在定义了一个函数,需要同时返回多个值,假设就是a,b,c三个变量,那么我们可以创建一个数组,在其中存储这三个变量的指针,然后将数组返回。

        一个指针的长度为8个字节,是一个long long型数据,所以这个函数的返回值类型为long long *

long long * func(){

}

        然后我们创建一个long long型数组,取各变量指针并强制转换为long long型数据,再将数组返回,就像这样:

long long * func(){
    ......
    long long ptr_arr[] = {(long long)&a, (long long)&b, (long long)&c};
    return ptr_arr;
}

        这是一段很庞杂的代码,不便书写,所以我们要用预编译语句对其进行简化

#define mul long long *    //将所有“mul”替换成“long long * ”
#define with (long long)&  //将所有“with”替换成“(long long)&”

        这样代码就可以简化如下:

mul func(){
    ......
    long long ptr_arr[] = {with a, with b, with c};
    return ptr_arr;
}

        再定义一个预编译语句,对代码进行整体简化:

//括号中的省略号表示不定参数
//“__VA_ARGS__”会被替换成括号中输入的内容
//反斜线(“\”)表示连接上下两行预编译指令
#define remul(...) long long ptr_arr[] = {__VA_ARGS__};\    
                   return ptr_arr

mul func(){
    ......
    remul(with a, with b, with c);
}

        ptr_arr这个变量名显得有些随意,换个正式点的

#define remul(...) long long __POINTERS_ARR__[] = {__VA_ARGS__};\    
                   return __POINTERS_ARR__

        接下来,我们需要在函数外接收这个数组,并对对应变量赋值:

long long * arr_ptr = func();
int val1 = *(int *)*(arr_ptr+0);
int val2 = *(int *)*(arr_ptr+1);
int val3 = *(int *)*(arr_ptr+2);

        稍微有点绕。*(arr_ptr+i)是读取这个数组对应位置的long long型数据,(int *)*(arr_ptr+i)是将这个long long型数据转换成一个int类型的指针,*(int *)*(arr_ptr+i)是将这个指针里的值取出来,赋给等号左边。(只是拿int型做个例子,事实上任何数据类型都可以)

        给它加个计数器:

int counter = 0;
long long arr_ptr = func();
int val1 = *(int *)*(arr_ptr+counter);
counter++;
int val2 = *(int *)*(arr_ptr+counter);
counter++;
int val3 = *(int *)*(arr_ptr+counter);
counter++;

        我们发现,这段代码可以抽象成这种形式:

int counter = 0; long long arr_ptr = func()
; int val1 = *(int *)*(arr_ptr+counter); counter++
; int val2 = *(int *)*(arr_ptr+counter); counter++
; int val3 = *(int *)*(arr_ptr+counter); counter++
;

        定义如下预编译指令:

#define from\
    int counter = 0; long long arr_ptr = 
#define to(value, type)\    //传入待赋值变量及其类型
    ; int value = *(type *)*(arr_ptr+counter); counter++

        原代码简化成如下形式:

from func() to (val1, int) to (val2, int) to (val3, int);

        这样一来就差不多完成了。

        整合一下预编译指令:

#define mul long long *
#define with (long long)&
#define remul(...) long long __POINTERS_ARR__[] = {__VA_ARGS__};\    
                   return __POINTERS_ARR__
#define from\
    int counter = 0; long long arr_ptr = 
#define to(value, type)\
    ; int value = *(type *)*(arr_ptr+counter); counter++

        发现还有个问题,那就是每次执行的都是“int counter”“int value”的指令,这样这两个变量就有被重复定义的风险。我们将它们的定义挪到前头:

int value;
int counter = 0;
#define mul long long *
#define with (long long)&
#define remul(...) long long __POINTERS_ARR__[] = {__VA_ARGS__};\    
                   return __POINTERS_ARR__
#define from\
    counter = 0; long long arr_ptr = 
#define to(value, type)\
    ; value = *(type *)*(arr_ptr+counter); counter++

        成品如下,你可以将其定义为一个头文件,在自己的项目中导入

int __POINTER_ARR_COUNTER__ = 0;
long long * __ARR_POINTER__;
#define mul long long *
#define with (long long)&
#define remul(...)\
    long long __POINTERS_ARR__[] = {__VA_ARGS__};\
    return __POINTERS_ARR__
#define from __POINTER_ARR_COUNTER__ = 0;\
             __ARR_POINTER__ = 
#define to(val, type) ;\
    val = *(type *)*(__ARR_POINTER__+__POINTER_ARR_COUNTER__);\
    __POINTER_ARR_COUNTER__++

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值