【整理】关于 va_copy 的兼容性问题
【整理】关于 va_copy 的兼容性问题
摩云飞 发表于4年前
【整理】关于 va_copy 的兼容性问题
  • 发表于 4年前
  • 阅读 87
  • 收藏 0
  • 点赞 0
  • 评论 0

新睿云服务器60天免费使用,快来体验!>>>   

摘要: 本文主要描述 va_copy 的兼容性问题。

首先查看 Linux 下的 man 信息。
[root@Betty ~]# man va_copy
STDARG(3)                  Linux Programmer’s Manual                 STDARG(3)

NAME
       stdarg - variable argument lists

SYNOPSIS
       #include <stdarg.h>

       void va_start(va_list ap, last);
       type va_arg(va_list ap, type);
       void va_end(va_list ap);
       void va_copy(va_list dest, va_list src);
  
  ...
  ...
  
   va_copy
       An  obvious implementation would have a va_list be a pointer to the stack frame of the variadic function.  
       In such a setup (by far the most common) there seems nothing against an assignment
       一种最常见的实现是将 va_list 作为指向变参函数栈帧的指针使用。在这种情况下(最常见情况),va_copy 的功能和下面的赋值操作可以等价
                   va_list aq = ap;
       Unfortunately, there are also systems that make it an array of pointers (of length 1), and there one needs
       不幸的是,有一些系统将 va_list 实现成了指针数组(长度为 1),故操作必须如下才能保证正确
                   va_list aq;
                   *aq = *ap;
       Finally, on systems where parameters are passed in registers, it may be necessary for va_start() to allocate 
       memory, store the parameters there, and also an indication of which parameter is next, so that va_arg() can 
       step through the list. Now va_end() can free the allocated memory again. To accommodate this situation, C99 
       adds a macro va_copy(), so that the above assignment can be replaced by
       在使用寄存器(register)传参的系统上,va_start() 函数会负责所需内存的分配以及相应参数值的存储,并且会指示下一个待处理的参数是
       谁,以便于 va_arg() 能够遍历变参列表。va_end() 会负责分配内存的释放工作。为了满足上述行为,C99 添加了宏定义 va_copy(),所以
       上面的赋值操作可以被下面的代码替代
                   va_list aq;
                   va_copy(aq, ap);
                   ...
                   va_end(aq);
       Each invocation of va_copy() must be matched by a corresponding invocation of va_end() in the same function.  
       Some systems that do not supply va_copy() have __va_copy instead, since that was the name used in the draft proposal.
       每一次对 va_copy() 的调用都必须与 va_end() 进行配对(同一个函数内部)。一些系统上不支持 va_copy() 但是提供了 __va_copy() 也
       是可以的,该名字的由来是因为在草案中就是这个。

CONFORMING TO
       The va_start(), va_arg(), and va_end() macros conform to C89.  C99 defines the va_copy() macro.
       va_copy() 是在 C99 中被支持的。

       有了上述信息,就可以大体确认了 VS2010 是不支持 va_copy() 的,同时发现其对 __va_copy() 也不支持。所以,只能自己实现一个替代方案了。

在 MySQL 5.6.10 中有如下的兼容性代码:
#ifndef va_copy
#define	va_copy(dst, src)	memcpy(&(dst), &(src), sizeof(va_list))
#endif
va_copy(aq, ap);

在 Jansson-2.5 库中的 jansson_private.h 中有如下定义

/* va_copy is a C99 feature. In C89 implementations, it's sometimes
   available as __va_copy. If not, memcpy() should do the trick. */
#ifndef va_copy
#ifdef __va_copy
#define va_copy __va_copy
#else
#define va_copy(a, b)  memcpy(&(a), &(b), sizeof(va_list))
#endif
#endif
       另外在 stackoverflow 上有关于这个问题的讨论:这里

标签: va_copy
  • 打赏
  • 点赞
  • 收藏
  • 分享
共有 人打赏支持
粉丝 360
博文 352
码字总数 952690
×
摩云飞
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: