首页 > C/C++语言, 编程语言 > C技巧:结构体参数转成不定参数

C技巧:结构体参数转成不定参数

2010年8月10日 发表评论 阅读评论 3,887 人阅读    

下面这段程序是一个C语言的小技巧,其展示了如何把一个参数为结构体的函数转成一个可变参数的函数,其中用到了宏和内建宏“__VA_ARGS__”,下面这段程序可以在GCC下正常编译通过:

#include <stdio.h>

#define func(...) myfunc((struct mystru){__VA_ARGS__})

struct mystru { const char *name; int number; };

void myfunc(struct mystru ms )
{
  printf("%s: %d\n", ms.name ?: "untitled", ms.number);
}

int main(int argc, char **argv)
{
  func("three", 3);
  func("hello");
  func(.name = "zero");
  func(.number = argc, .name = "argc",);
  func(.number = 42);
  return 0;
}

从上面这段程序,我们可以看到一个叫 myfunc的函数,被func的宏改变了,本来myfunc需要的是一个叫mystru的结构,然而通过宏,我们把struct mystru的这个参数,变成了不定参数列表的一个函数。上面这段程序输出入下,

three: 3
hello: 0
zero: 0
argc: 1
untitled: 42

虽然,这样的用法并不好,但是你可以从另外一个方面了解一下这世上对C稀奇古怪的用法。 如果你把宏展开后,你就明的为什么了。下面是宏展开的样子:

  myfunc((struct mystru){"three", 3});
  myfunc((struct mystru){"hello"});
  myfunc((struct mystru){.name = "zero"});
  myfunc((struct mystru){.number = argc, .name = "argc",});
  myfunc((struct mystru){.number = 42});




分类: C/C++语言, 编程语言 标签:
好烂啊有点差凑合看看还不错很精彩 (5 人打了分,平均分: 4.20 )
Loading ... Loading ...
  1. 2010年8月10日08:38 | #1

    我倒是第一次见到那个问号紧跟冒号的用法。

  2. thornyroad
    2010年8月10日08:43 | #2

    很强大。

    不过想问下,楼主说这样的用法并不好。请问:这样的用法缺点是什么?有没有可能进行改进加强,而变成一种好的惯用法?

  3. bugthat
    2010年8月10日10:28 | #3

    @GlacJAY
    我也是第一次见,三目运算符a?b:c的特例吧,测试了一下果真如此,这样写倒是省事,但别人不一定理解

  4. 电子骑士
    2010年8月10日10:29 | #4

    @thornyroad
    这样写的程序,可读性会非常差,如果不是程序员本人,你说别人要看懂得花多大功夫?
    另外的局限性是,可变参数仅限于定义的结构体里面有限的参数,就灵活程序比不性真正的可变参数函数。

  5. jruv
    2010年8月10日10:49 | #5

    这个只在gcc中能编译吧, 好像那些都是gcc的extention啊

  6. 2010年8月10日10:56 | #6

    很明显,这是一种滥用。这篇文章的主旨并不是提倡这样的做法,而是告诉你一些这世界上的怪招,让大家开开眼。

  7. jruv
    2010年8月10日11:00 | #7

    thornyroad :
    很强大。
    不过想问下,楼主说这样的用法并不好。请问:这样的用法缺点是什么?有没有可能进行改进加强,而变成一种好的惯用法?

    移植性比较差吧,可读性还好吧

  8. saint23
    2010年8月10日13:07 | #8

    这段代码错误太多了,不看也罢

  9. 2010年8月10日15:58 | #9

    怎么感觉像是在函数变量的初始化,但好像复杂了点。第一次见到这样写的。

  10. 2010年8月10日18:28 | #10

    @陈皓
    呵呵,这个虽说是一个滥用,但从另外一个角度来说,也可以认为是一种利用c语言来开发一种dsl:)

  11. 2010年8月10日22:51 | #11

    这个好像是c99新增的,但是gcc似乎不用-std=c99选项也能编译的……
    另外博主能把主页上上篇博文中的ui效果屏蔽掉么?弄得我现在打开很卡的….

  12. bigship
    2010年8月11日11:57 | #12

    又一个trick :D
    这个方法允许我们能直接以函数调用的形式对结构体中某些感兴趣的字段赋值,然后呼叫函数。
    一般情况下,我们只能先填结构体,再呼叫函数。
    struct mystru ms
    {
    .xx = xxx;
    .yy = xxx;
    .zz = xxx;
    };
    myfunc(ms);
    现在可以直接func(.xx = “zero”);
    好处嘛,代码行数减少了:D,缺点是可能这种写法不可移植,且有些晦涩,有玩弄技巧之嫌。
    Anyway, thanks for sharing

  13. 2010年8月11日20:40 | #13

    C稀奇古怪的用法确实很多,java中也有,不过如果是团队开发,还是提倡合乎规范的做法。

  14. 2010年8月17日11:13 | #14

    第一次见这种写法,学习了。

  15. xty_seven
    2010年10月9日16:46 | #15

    长见识了! 不过没看到实用性!

  1. 本文目前尚无任何 trackbacks 和 pingbacks.

无觅相关文章插件,快速提升流量