gpt4 book ai didi

c - 指向 amd64 ABI 中的 va_list 的指针

转载 作者:太空狗 更新时间:2023-10-29 15:36:34 24 4
gpt4 key购买 nike

我担心 Linux amd64 (x86_64) 下的可变参数函数。

我的示例在 linux i386 (ia32) 上构建并运行良好,但在为 linux amd64 构建时,GCC 产生这样的错误:

stdarg.c: In function ‘vtest’:
stdarg.c:21:5: attention : passing argument 2 of ‘vptest’ from incompatible pointer type [enabled by default]
stdarg.c:5:1: note: expected ‘struct __va_list_tag (*)[1]’ but argument is of type ‘struct __va_list_tag **’

这里是例子:

#include <stdio.h>
#include <stdarg.h>

static int
vptest(int count, va_list *a)
{
printf("%8s: a = %p\n", __func__, a);
printf("%8s: %d: %d\n", __func__, count, va_arg(*a, int));
return 0;
}

static int
vtest(int count, va_list ap)
{
printf("%8s: &ap = %p\n", __func__, &ap);

/* passing a pointer to ap allows ap to be used again in the calling function */
for(; count > 1; count --) {
vptest(count, &ap);
}
if (count) {
printf("%8s: %d: %d\n", __func__, count, va_arg(ap, int));
}
return 0;
}

static
int test(int count, ...)
{
va_list ap;

va_start(ap, count);
printf("%8s: &ap = %p\n", __func__, &ap);

/* after passing ap to subfunction, this function must not use ap again without calling va_start */
vtest(count, ap);

va_end(ap);

return 0;
}

int
main(void)
{
test(4,
1, 2, 3, 4);

return 0;
}

根据 C11 draft (ISO/IEC 9899:2011)

The object ap may be passed as an argument to another function; if that function invokes the va_arg macro with parameter ap, the value of ap in the calling function is indeterminate and shall be passed to the va_end macro prior to any further reference to ap.

但后者补充

It is permitted to create a pointer to a va_list and pass that pointer to another function, in which case the original function may make further use of the original list after the other function returns.

我不清楚 AMD 64 ABI此处认为标准是错误的

将函数 vtest() 更改为在第一次调用时使用指针解决了这个问题,但在内部函数中不起作用的东西实际上在外部函数中起作用感觉不对。

@@ -12,16 +12,16 @@
}

static int
-vtest(int count, va_list ap)
+vtest(int count, va_list *a)
{
- printf("%8s: &ap = %p\n", __func__, &ap);
+ printf("%8s: a = %p\n", __func__, a);

/* passing a pointer to ap allows ap to be used again in the calling function */
for(; count > 1; count --) {
- vptest(count, &ap);
+ vptest(count, a);
}
if (count) {
- printf("%8s: %d: %d\n", __func__, count, va_arg(ap, int));
+ printf("%8s: %d: %d\n", __func__, count, va_arg(*a, int));
}

return 0;
@@ -37,7 +37,7 @@
printf("%8s: &ap = %p\n", __func__, &ap);

/* after passing ap to subfunction, this function must not use ap again without calling va_start */
- vtest(count, ap);
+ vtest(count, &ap);

va_end(ap);

如果有人能找到某处 AMD64 ABI 行为是否符合标准。对于向我提供其他 ABI 并在 stdarg 使用方面有(相同)问题的人的额外要点。

问候

最佳答案

行为是完全一致的,因为尽管 vtest 的参数被写成 va_list apap 没有类型 va_list 而不是 va_list 衰减成的任何指针类型。这是符合标准的,因为标准允许 va_list 是数组类型。这个问题的解决方法是使用va_copyap复制到本地va_list:

va_list ap2;
va_copy(ap2, ap);
// ...
vptest(count, &ap2);
// ...
va_end(ap2);

由于 ap2 的定义和类型在您的控制之下,&ap2 具有传递给 vptest 的正确类型。

关于c - 指向 amd64 ABI 中的 va_list 的指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9792834/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com