icemanpro
V2EX  ›  C

如何将 list 转换成可变长参数?

  •  
  •   icemanpro · Jan 29, 2019 · 4076 views
    This topic created in 2688 days ago, the information mentioned may be changed or developed.
    现有一函数 void foo(int count,...) ,因参数长度是在运行时才确定的,现将参数放入到一 list 中,如何调用 foo ,并将 list 做为参数传给 foo?
    11 replies    2019-01-29 16:54:06 +08:00
    eritpchy
        1
    eritpchy  
       Jan 29, 2019
    直接传递 va_list 会好点
    GeruzoniAnsasu
        2
    GeruzoniAnsasu  
       Jan 29, 2019
    本来想说不能这么传

    然后再看了几遍。。。。foo 是已存在已定义不可改的接口吗。。那我觉得没有写法能帮你

    va_list 在 x64 上没法用
    icyalala
        3
    icyalala  
       Jan 29, 2019
    试试 libffi
    @GeruzoniAnsasu va_list 在 x64 上为什么没法用?
    GeruzoniAnsasu
        4
    GeruzoniAnsasu  
       Jan 29, 2019
    @icyalala 其实是不太想解释

    首先如果是传参数进来,在函数里用 va_系列宏去解开传进来的变长参数,是可以用的,因为 x64 默认的 fastcall 约定虽然用寄存器传参,但会在栈上放一个副本,还是有地址可引用。不过放副本这个操作是被调函数的 prologue 做的,从外面打包参数进来的时候前 4 个参数还是只会通过寄存器传递。

    如果非要 hack 的话确实可以内嵌一下汇编先把前 4 个参数放进寄存器其余的压栈,但这样 hack 的话连 call 也必须要用汇编嵌进去并且返回后手动 add rsp 恢复栈平衡,更要命的是在 win 和 linux 上同样是 fastcall 约定用到的寄存器还不一样,还得针对平台写两套汇编

    虽然总共代码也不多,但总觉得崩的可能性太大了,想强迫 lz 先想其它的方法解决
    GeruzoniAnsasu
        5
    GeruzoniAnsasu  
       Jan 29, 2019
    啊。。。原来 fastcall 是用 6 个寄存器
    icyalala
        6
    icyalala  
       Jan 29, 2019
    @GeruzoniAnsasu calling convention 不单只有 fastcall,参数也不单是 integer 类型,没必要重新实现一遍 libffi 嘛。。
    catror
        7
    catror  
       Jan 29, 2019
    enenaaa
        8
    enenaaa  
       Jan 29, 2019
    @GeruzoniAnsasu 不定参数调用使用__cdecl 方式吧。 跟 fastcall 有啥关系。
    pursuer
        9
    pursuer  
       Jan 29, 2019
    @enenaaa
    x86_64 操作系统规定的 abi 好像已经统一成类似 fastcall 的寄存器传参了,而且不同操作系统的 abi 还不一样
    GeruzoniAnsasu
        10
    GeruzoniAnsasu  
       Jan 29, 2019
    @icyalala
    @catror
    @enenaaa
    可以理解为,x64 只有一种调用约定,但有两个不同平台版本的实现
    尝试在编译到 x64 的源码函数上声明 stdcall 或 cdecl 都会被编译器忽略

    另外不定参函数这种东西,在 C++中必定是与变参模板同时存在的,在 C 中,变参函数实际上就是变参泛型的 approach, “运行时不定个数”类的东西不会用变参函数来写,一定会封装成某种数据结构并把指针传进去。无论 C 还是 C++,变参函数都是用来方便“静态不定个数参数的调用”的,C++通过变参模板给它加了更强的约束而已。

    所以最开始就想说,参数不能像 lz 设想的那样传,传一个“运行时不定长”的东西给变参函数本来就是错误的做法
    eritpchy
        11
    eritpchy  
       Jan 29, 2019
    https://stackoverflow.com/a/3968787
    代码虽丑但可以解决问题
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   5576 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 55ms · UTC 07:38 · PVG 15:38 · LAX 00:38 · JFK 03:38
    ♥ Do have faith in what you're doing.