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

简介:

首先查看 Linux 下的 man 信息。
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
[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 中有如下的兼容性代码:  
?
1
2
3
4
#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 中有如下定义

?
1
2
3
4
5
6
7
8
9
/* 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
目录
相关文章
|
3月前
|
C++
stl中copy注意的地方
stl中copy注意的地方
|
10月前
|
Oracle Java 关系型数据库
华为云aarch64架构下载jdk;Linux上jdk无法执行二进制文件及​gzip: stdin: invalid compressed data–format violated​报错
华为云aarch64架构下载jdk;Linux上jdk无法执行二进制文件及​gzip: stdin: invalid compressed data–format violated​报错
298 0
|
Python
Python基础-常见问题:运行代码时提示“SyntaxError: expected an indented block”,怎么解决呢?
Python基础-常见问题:运行代码时提示“SyntaxError: expected an indented block”,怎么解决呢?
267 0
|
Python
Python 库兼容性问题-fromstring() has been removed. Please call frombytes() instead.原因及解决办法
Python 库兼容性问题-fromstring() has been removed. Please call frombytes() instead.原因及解决办法
127 0
Python 库兼容性问题-fromstring() has been removed. Please call frombytes() instead.原因及解决办法
linux中{}的常规用法
初学linux的脚本,对于linux中的{}用法记录一下