You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何无中间变量将结构体克隆函数返回值以指针形式传入函数?

问题分析

你遇到的这个问题本质上是C语言里左值和右值的区别在搞怪:

  • 当你调用my_struct_clone(other, 123)时,函数返回的是一个临时的结构体对象——这是一个右值。C语言规则明确禁止对右值使用&运算符(因为右值没有持久的内存地址,或者说它的地址是无意义的),所以&(my_struct_clone(...))会触发编译器错误。
  • 而复合字面量(struct my_struct){.a=1,.b=2}是一个左值,它会在当前代码块中创建一个有作用域的临时结构体实例(虽然你没给它命名),所以可以合法取地址。

标准C解决方案:用复合字面量包裹返回值

既然复合字面量是左值,我们可以用它来“承接”克隆函数返回的临时结构体,这样就能合法取地址传给do_sth,完全不需要中间变量:

do_sth(&(struct my_struct){ my_struct_clone(other, 123) });

这个写法的原理是:

  1. 复合字面量(struct my_struct){ ... }会在当前代码块中分配一个临时结构体实例
  2. 用my_struct_clone返回的结构体来初始化这个实例
  3. 取这个实例的地址传给do_sth
  4. 这个临时实例的生命周期会持续到当前代码块结束,完全足够do_sth完成同步执行(不会出现悬空指针问题)

简化写法:用宏减少重复代码

如果要多次用到这个逻辑,可以写一个宏来避免重复写结构体类型:

#define PASS_CLONED_STRUCT(clone_expr) (&(struct my_struct){ clone_expr })

// 调用起来更简洁:
do_sth(PASS_CLONED_STRUCT(my_struct_clone(other, 123)));

可选:GNU C扩展的语句表达式

如果你使用GCC或Clang这类支持GNU扩展的编译器,还可以用语句表达式来实现更直观的写法:

do_sth(({ 
    struct my_struct tmp = my_struct_clone(other, 123); 
    &tmp; 
}));

语句表达式会执行括号内的代码块,最后返回最后一行表达式的值(也就是临时变量tmp的地址)。这个写法和你原来用中间变量的逻辑几乎一样,但可以压缩到一行里,而且不需要额外的宏。不过要注意这不是标准C,移植性会稍差。

另一种思路:修改克隆函数接口

如果你能修改克隆函数的定义,也可以改成“输出参数”的形式,直接把结果写入你提供的指针里:

// 修改后的克隆函数
inline void my_struct_clone(struct my_struct *dst, struct my_struct src, int members) {
    *dst = (struct my_struct){0}; // 先初始化
    // 根据members克隆成员,比如:
    if (members & 1) dst->a = src.a;
    if (members & 2) dst->b = src.b;
}

// 结合复合字面量的调用方式(GNU扩展):
do_sth(({ 
    struct my_struct tmp = {0}; 
    my_struct_clone(&tmp, other, 123); 
    &tmp; 
}));

不过这种方法其实还是绕不开临时变量,只是把克隆逻辑移到了函数内部,对你来说可能不如前面的方案简洁。

内容的提问来源于stack exchange,提问作者Twifty

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 09:14:17