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

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

下面这段程序是一个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});


关注CoolShell微信公众账号可以在手机端搜索文章

(转载本站文章请注明作者和出处 酷 壳 – CoolShell ,请勿用于任何商业用途)

——=== 访问 酷壳404页面 寻找遗失儿童。 ===——
好烂啊有点差凑合看看还不错很精彩 (5 人打了分,平均分: 4.20 )
Loading...

C技巧:结构体参数转成不定参数》的相关评论

  1. 很强大。

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

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

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

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

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

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

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

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

  8. linux编译出现以下错误 求解答
    test1.cpp:19: error: expected primary-expression before ‘)’ token
    在这句上 func(.name = “zero”);

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*