12-9 案例:处理复杂的线程返回结果

1. 问题来源

        thrd_create() 函数功能为新建一个线程,传入待执行的函数。待执行函数的格式要求如下:

typedef int (*thrd_start_t)(void *arg);

        这意味着待执行函数只能返回 int 类型值,接收 void* arg 参数。若待执行函数想要返回一个结构体,该如何操作?

2. 解决方案        

        解决方案一:由于返回值为 int 类型,指针的本质也是一串数字,所以可将结构体指针进行返回,从而返回结构体

#include <stdio.h>
#include <tinycthread.h>
#include <stdlib.h>

// 待返回的结构体
typedef struct {
  int a;
  char *b;
} ComplexResult;

int ComplexReturnValue(void *arg){

  ComplexResult *complex_result = malloc(sizeof(ComplexResult));
  complex_result->a = 1;
  complex_result->b = "hello";

  return complex_result; // 返回结构体指针
}

void TestComplexReturn(){

  thrd_t t;
  thrd_create(&t, ComplexReturnValue, NULL);

  int result;
  thrd_join(t, &result);

  ComplexResult *complex_result = (ComplexResult *)result; // 函数结果强转为结构体指针类型

  printf("complex_result->a: %d\n", complex_result->a);
  printf("complex_result->a: %s\n", complex_result->b);
}

        注意,在 ComplexReturnValue() 函数中使用 malloc 创建结构体指针,而不是新建 ComplexResult 结构体。原因在于新建的结构体存储在函数栈上,一旦函数退出,结构体的内存会被释放。使用 malloc 创建的结构体指针,其指向的结构体存储在堆区中,不会随着函数退出而释放,需要使用 free() 主动释放(https://blog.csdn.net/gltzlike/article/details/114649846)。

        在 32 位 msvc 编译器下运行结果无误,而在 64 位 msvc 编译器下运行出错。原因在于指针类型和 int 类型的强制转换,32 位系统下指针类型大小为 4 个字节,与 int 类型大小相同,所以程序可正常运行。64 位系统下指针类型大小通常为 8 个字节,强转为 int 类型会出错,故程序执行错误。

         解决方案二:函数返回值的设置是为了获取到被函数修改后的变量。将指针作为函数参数,在函数执行过程中对指针指向的内容进行更改,从而实现与函数返回值相同的功能。例如:

void change(int *temp){
  *temp = 4;
}

void Test(){

  int a = 2;
  int *p = &a;
  change(p);

  printf("a: %d\n", a);  // a: 4
}

        同理,将结构体指针作为函数参数,在函数执行过程中对结构体相关内容进行更改,其功能和返回结构体相同。由于对结构体指针进行操作,即直接对内存进行操作,所以结构体相关的变量可以直接被修改。

#include <stdio.h>
#include <tinycthread.h>
#include <stdlib.h>

typedef struct {
  int a;
  char *b;
} ComplexResult;

int ComplexReturnValue(ComplexResult *arg){

  ComplexResult *complex_result = arg;
  complex_result->a = 1;
  complex_result->b = "hello";

  return 0;
}

void TestComplexReturn(){

  thrd_t t;

  // ComplexResult *complex_result = malloc(sizeof(ComplexResult));

  ComplexResult complex_result;
  thrd_create(&t, ComplexReturnValue, &complex_result);

  int result;
  thrd_join(t, &result);

  printf("complex_result->a: %d\n", complex_result.a);
  printf("complex_result->b: %s\n", complex_result.b);
}

3. 总结

        函数若要返回复杂的返回值(例如结构体),解决方法之一便是利用函数参数解决。解决方法之二是使用函数回调,见下一小节。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值