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 ,请勿用于任何商业用途)
《C技巧:结构体参数转成不定参数》的相关评论
我倒是第一次见到那个问号紧跟冒号的用法。
很强大。
不过想问下,楼主说这样的用法并不好。请问:这样的用法缺点是什么?有没有可能进行改进加强,而变成一种好的惯用法?
@GlacJAY
我也是第一次见,三目运算符a?b:c的特例吧,测试了一下果真如此,这样写倒是省事,但别人不一定理解
@thornyroad
这样写的程序,可读性会非常差,如果不是程序员本人,你说别人要看懂得花多大功夫?
另外的局限性是,可变参数仅限于定义的结构体里面有限的参数,就灵活程序比不性真正的可变参数函数。
这个只在gcc中能编译吧, 好像那些都是gcc的extention啊
很明显,这是一种滥用。这篇文章的主旨并不是提倡这样的做法,而是告诉你一些这世界上的怪招,让大家开开眼。
移植性比较差吧,可读性还好吧
这段代码错误太多了,不看也罢
怎么感觉像是在函数变量的初始化,但好像复杂了点。第一次见到这样写的。
@陈皓
呵呵,这个虽说是一个滥用,但从另外一个角度来说,也可以认为是一种利用c语言来开发一种dsl:)
这个好像是c99新增的,但是gcc似乎不用-std=c99选项也能编译的……
另外博主能把主页上上篇博文中的ui效果屏蔽掉么?弄得我现在打开很卡的….
又一个trick :D
这个方法允许我们能直接以函数调用的形式对结构体中某些感兴趣的字段赋值,然后呼叫函数。
一般情况下,我们只能先填结构体,再呼叫函数。
struct mystru ms
{
.xx = xxx;
.yy = xxx;
.zz = xxx;
};
myfunc(ms);
现在可以直接func(.xx = “zero”);
好处嘛,代码行数减少了:D,缺点是可能这种写法不可移植,且有些晦涩,有玩弄技巧之嫌。
Anyway, thanks for sharing
C稀奇古怪的用法确实很多,java中也有,不过如果是团队开发,还是提倡合乎规范的做法。
第一次见这种写法,学习了。
长见识了! 不过没看到实用性!
linux编译出现以下错误 求解答
test1.cpp:19: error: expected primary-expression before ‘)’ token
在这句上 func(.name = “zero”);
这种方法不值得在项目中应用。但我们应该知道,以防某天要看懂这些代码