文档章节

【整理】关于 va_copy 的兼容性问题

摩云飞
 摩云飞
发布于 2013/12/18 15:43
字数 674
阅读 97
收藏 0

首先查看 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 上有关于这个问题的讨论:这里

© 著作权归作者所有

共有 人打赏支持
摩云飞
粉丝 368
博文 534
码字总数 952694
作品 0
徐汇
程序员
C语言深入浅出可变参数函数的使用技巧

C语言深入浅出可变参数函数的使用技巧(转) 深入浅出可变参数函数的使用技巧本文主要介绍可变参数的函数使用,然后分析它的原理,程序员自己如何对它们实 现和封装,最后是可能会出现的问题...

Start-up
2012/10/19
0
0
Effective C++: 省略符形参

Notice: 省略符形参并不是可变模板参数! 同时这是针对非模板的可变参数解决方案!!!!!!! 再C中有一个函数: int printf(const char* format, ...); 这里的 "..."一直不明白是什么意思,...

SHIHUAMarryMe
2016/11/23
35
0
可变参数: va_start,va_arg,va_end

vastart,vaarg,va_end是在stdarg.h中被定义成宏的, 由于1)硬件平台的不同 2)编译器的不同,所以定义的宏也有所不同,下 面以VC++中stdarg.h里x86平台的宏定义摘录如下(’’号表示折行): typede...

Start-up
2012/05/08
0
0
深入浅出VA函数

VA函数(variable argument function),参数个数可变函数,又称可变参数函数。C/C++编程中,系统提供给编程人员的va函数很少。printf()/scanf()系列函数,用于输入输出时格式化字符串;exe...

XDATAPLUS
2016/06/13
0
0
函数可变参数

#include include using namespace std; // 求若干数的平方和//第一个参数是参数的个数double pingfangsum(int a,...){double sum = 0,num;valist vararg; //定义一个指向个数可变的参数列表...

晨曦之光
2012/04/13
67
0

没有更多内容

加载失败,请刷新页面

加载更多

nginx的简单使用:负载均衡

nginx:反向代理的服务器;用户发送请求到nginx,nginx把请求发送给真正的服务器,等待服务器处理完数据并返回,再把数据发送给用户。 nginx作为一个反向代理服务器,能缓存我们项目的静态文...

osliang
13分钟前
1
0
网站title标题被改并被百度网址安全中心提醒的解决办法

国庆假日期间我们Sine安全接到众多网站站长求助网站标题被改导致在百度搜索中百度安全中心提醒被拦截,导致网站正常用户无法浏览网站被跳转到一些菠菜du博网站,而且很明显的一个特征就是在百...

网站安全
15分钟前
1
0
JDK版本与major.minor version的对照关系

其实,只需要记住jdk6对于major.minor version 50即可,其他版本自行计算即可。 ---------------------

码代码的小司机
17分钟前
1
0
Gitlab安装

具体步骤如下: sudo yum install -y curl policycoreutils-python openssh-server cronie sudo lokkit -s http -s ssh sudo yum install postfix sudo service postfix start sudo chkconfi......

很好亦平凡ms
25分钟前
1
0
C++基础教程面向对象学习笔记及心得感悟[图]

C++基础教程面向对象学习笔记及心得感悟[图] 使用友元函数重载算术运算符: C ++中一些最常用的运算符是算术运算符 - 即加号运算符(+),减运算符( - ),乘法运算符(*)和除法运算符(/...

原创小博客
26分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部