va_list 32位和64位不兼容

来源:互联网 发布:怎么查询网络密匙 编辑:程序博客网 时间:2024/04/30 05:02

这两天将程序移植到64位上,以下代码在32位linux上完全没有问题,但是在64位linux上不能编译通过:

 

std::vector<char*> vecCharVar;

......

INT32 nprint = vsnprintf(szQuery, sizeof(szQuery), strSQLFormat.c_str(), reinterpret_cast<va_list>(&vecCharVar[0]));

编译时报错:

cannot convert from char** to va_list

在网上查资料,才知道在64位下,va_list已经不是指针了,而是一个24字节的结构体。搜了好多帖子,倒是有人和我遇到了完全一样的问题:

http://stackoverflow.com/questions/11691189/vsprintf-how-to-convert-void-to-va-list-on-linux

http://stackoverflow.com/questions/4535050/how-to-create-a-va-list-on-gcc

网上有各种正确的分析,可以都没有很简便的解决方法。有人提到libffi库可以解决这个问题:

http://www.atmark-techno.com/~yashi/libffi.html -- simple example given

http://www.swig.org/Doc1.3/Varargs.html -- printf() and other examples given

 

我没有去研究libffi,因为代码中应用很简单,格式化字符串中只有%s,所以手动写了个函数组装动态参数:

bool GetFormatDBStr(string &outStr, string strFormat, vector<const char *> &vecArg)
{
 size_t iVecIdx = 0;
 string::size_type iStart = 0, iPos;

 iPos = strFormat.find("%s", iStart);
 while(string::npos != iPos)
 {
  outStr += strFormat.substr(iStart, iPos - iStart);

  if(iPos>iStart && '%'==strFormat.at(iPos-1))  // %前面有转义字符
  {
   outStr += strFormat.substr(iPos, 2);
  }
  else
  {
   if(iVecIdx >= vecArg.size() || NULL == vecArg[iVecIdx])
   {
    return false;
   }

   outStr += vecArg[iVecIdx];
   iVecIdx++;
  }

  iStart = iPos + 2;
  iPos = strFormat.find("%s", iStart);
 }

 if(iStart < strFormat.size())
 {
  outStr += strFormat.substr(iStart, strFormat.size() - iStart);
 }

 return iVecIdx == vecArg.size();
}

 

代码从32位移植到64位,比较简单,可是还是会遇到各种问题。引用帖子中一个老外的回复:

You may take it that I was surprised to find this much discrepancy between the 32-bit and 64-bit versions.


0 0
原创粉丝点击