在编译器之间匹配va_list类型

Car*_*rum 8 c gcc visual-studio-2003 variadic-functions

我有一个由一堆动态加载的模块组成的项目.最初,一切都是用MSVC 2003构建的,但最近我一直在努力让它与GCC一起工作.除了一个问题,一切都很顺利.对于64位代码,GCC和MSVC不同意它是什么va_list.对于32位,事情看起来很好.64位不匹配导致的问题是,使用一个编译器构建的模块具有带va_list参数的公共函数,并且该函数是从其他编译器构建的模块调用的.

除了第7.15节变量论证va_list之外,规范没有说明是什么,第3段:<stdarg.h>

声明的类型是

va_list

其适合用于保持由宏所需信息的对象类型va_start,va_arg,va_end,和va_copy.

那一段只是意味着这是所有编译器相关的东西 - 所以,有没有办法让这两个编译器就64位的内容达成一致va_list?对我的系统影响最小,使GCC与MSVC匹配va_list最好,但我会采取任何我能得到的解决方案.

谢谢你的帮助!

编辑:

我做了一些32位测试,我也有问题,这让我感到惊讶,因为任何32位Intel平台之间都没有ABI差异.我正在使用的MSVC代码库将所有可变参数函数宏定义为:

typedef char *va_list;
#define intsizeof(n)    ((sizeof(n) + sizeof(int) - 1) &~(sizeof(int) - 1))
#define va_start(ap, v) (ap = (va_list)&(v) + intsizeof(v))
#define va_arg(ap, t)   (*(t *) ((ap += intsizeof(t)) - intsizeof(t)))
#define va_end(ap)      (ap = (va_list)0)
Run Code Online (Sandbox Code Playgroud)

我从实际项目中略微简化了一下,但这是我用于测试的代码.使用GCC,这段代码肯定没有正确得到我的论点.也许这只是一个bug,正如Zack在下面所说的那样?

再次编辑:

我得到的工作成果与下列32位测试应用程序-O0,-O0和-O2,但不-O3,-Os和-Oz:

typedef char *va_list;
#define intsizeof(n)    ((sizeof(n) + sizeof(int) - 1) &~(sizeof(int) - 1))
#define va_start(ap, v) (ap = (va_list)&(v) + intsizeof(v))
#define va_arg(ap, t)   (*(t *) ((ap += intsizeof(t)) - intsizeof(t)))
#define va_end(ap)      (ap = (va_list)0)

int printf(const char *format, ...);

int f(int n, ...)
{
  int r = 0;
  va_list ap;

  va_start(ap, n);  
  while (n--)
    r = va_arg(ap, int);
  va_end(ap);

  return r;
}

int main(int argc, char **argv)
{
  int r;

  r = f(1, 1, 2, 3, 4, 5);
  printf("%x\n", r);

  r = f(2, 1, 2, 3, 4, 5);
  printf("%x\n", r);

  r = f(3, 1, 2, 3, 4, 5);
  printf("%x\n", r);

  r = f(4, 1, 2, 3, 4, 5);
  printf("%x\n", r);

  r = f(5, 1, 2, 3, 4, 5);
  printf("%x\n", r);

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

zwo*_*wol 5

由于MSVC定义了Win64 ABI,因此您在GCC中发现了一个错误.请在GCC bugzilla中报告.