- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我担心 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 ap
,ap
没有类型 va_list
而不是 va_list
衰减成的任何指针类型。这是符合标准的,因为标准允许 va_list
是数组类型。这个问题的解决方法是使用va_copy
将ap
复制到本地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/
尝试编译此代码时 #include void bar_ptr(int n, va_list *pvl) { // do va_arg stuff here } void bar(int n,
假设我有一个函数,它接受可变参数 (...) 或从另一个此类函数传递的 va_list 。主要逻辑在这个函数本身(我们称之为 f1),但我想让它将 va_list 传递给另一个函数(我们称之为 f2)
看似简单的问题,但一直未能在 SO 或 C 标准中找到答案。问题是 va_list 是否必须是 C 中函数的最后一个参数(当然,假设该函数将 va_list 作为参数)。 例如,这样安全吗? int
我正在尝试打印字符串类型的参数变量,但我一直卡在这上面 想法 尝试使用 _Str[i] 作为 while 循环内的表达式在 srting 内部移动,一旦 _Str[i] == '\0' 返回 (-1
下面的 max 函数应该返回 5,但它返回的是 4294967294。我怀疑奇怪的行为是由变量转换引起的,但无法弄清楚。有人能检测出故障吗? 系统:Windows 7(64位),mingw64 #in
在 Fedora 11 上编译一些工作代码时,我收到此错误: /usr/include/c++/4.4.1/cstdarg:56: error: ‘::va_list’ has not been de
全部, 我想控制 va_list 中的传递参数的数量。 va_list args; va_start(args, fmts); vfprintf(stdout, fmts, args)
我有一个很好的 C++ 函数,它通过 va_list + va_start + va_arg 支持多个参数。但我必须将我的项目转换为 C。转换后,这个 va_list 构造被编译器拒绝(多个错误)。有
我已经编写了这段代码,但我不确定它是否可以。 size_t sendHeaders(int fd, int seconds, const char* header1, ...) { size_
我无法找到我的“问题”的答案。 我创建了一个函数,它接受不同数量的整数('findMinVal(int x, ...)')并返回所有调用中的最小数字。现在我的程序直接通过代码获取参数: int mai
我一直在追踪一个问题,并将范围缩小到这个框架: #include #include #include #include #include #include typedef struct _
我有一个主要更新,我在通话前进行访问控制。我想在我的代码中使用一个地方来调用任何紧急函数。 我有一个结构 ACTION: { FUNC_PROTOTYPE pfnAction; uns
我目前有 2 个函数重载: void log(const char* format, ...); void log(const string& message); 我希望在这个调用的情况下:log("
在 case 's' 下,我得到一个坏指针 (0xcccccccc) 异常: string Logger::format(const char *str, va_list args) { os
#include #include void s(const char* param, ...) { va_list arguments; va_start (arguments,
我试着写一个这样的函数: int solve(double* x, double xA, double xB, double zeps, double funct(double x
我有这样的代码 #include "atlstr.h" void DisplayMessage(CString pszFormat, ...) { CString str; va_l
我正尝试在 C++ 中为一个项目实现一种反射形式。这个想法是,您将带有标签的类作为一种模板注册到映射中,然后调用共享基类的 cloneNew 方法来实际创建您想要的对象。但是,当我尝试使用 va_li
我已经(简单地)编写了这段代码。但它需要两次修复才能确定。 size_t send_header(int fd, int seconds, const char* header1, ...) {
我有一个用于微 Controller 的以太网库(用于 lpc2478 的 keil rl-tcpnet)。库以这种方式在调试输出函数中使用 va_list(指向 stdarg.h 中定义的 arg
我是一名优秀的程序员,十分优秀!