【问题标题】:c++ va_arg typecast issuec++ va_arg 类型转换问题
【发布时间】:2010-12-29 20:28:13
【问题描述】:

全部,

我正在编写一个小型 c++ 应用程序,但被这个问题难住了。如果不期望元素类型,有没有办法在使用 va_arg 从 va_list 宏访问元素时创建(以及稍后捕获)错误。例如:-

count=va_arg(argp,int); 
if (count <= 0 || count > 30)
{   
      reportParamError();   return;
}

现在,如果我传递 typedef 而不是 int,我会在 MS 编译器上得到垃圾值,但 95% 的时间计数在 gcc 上得到值 0(在 64 位 sles10 sys 上)。有没有办法可以强制执行一些类型检查,以便我得到一个可以在 catch 块中捕获的错误?

对此的任何想法都会对我很有帮助。或者有没有更好的方法来做到这一点。函数原型为:-

 void process(App_Context * pActx, ...) 

函数被称为

 process(pAtctx,3,type1,type2,type3);

pActx 必须作为第一个参数传递,因此不能将计数作为第一个参数传递。


更新-1

好的,这听起来很奇怪,但 nargs 似乎不是 sles10 gcc 上 va_list 的一部分。我不得不投入

#ifdef _WIN32
tempCount=va_arg(argp,int)
#endif

使用后,nargs 后面的参数不会得到垃圾值。但是,这引入了基于编译器/平台的#ifdefs....感谢 Chris 和 Kristopher

【问题讨论】:

  • 为什么不将计数作为第二个参数? void process(App_Context *pActx, std::size_t nargs, ...);
  • @Chris,感谢您的建议。我已经选择了那个选项,但是使用 gcc , nargs 之后的第一个参数(type1)正在获取垃圾值。最后一个参数也获取垃圾值。我假设 nargs 在 va_start(argp,App_Context *) 后跟 va_arg(argp,int) 的意义上也是 va_list 的一部分。

标签: c++ variadic-functions


【解决方案1】:

如果您知道计数将始终作为第二个参数传递,那么您可以随时将签名更改为:

void process(App_Context * pActx, int count, ...) 

如果这不是一个选项,那么真的没有办法抓住它。这就是 variable-argument-list 的工作原理:除了调用者传递的任何信息之外,被调用者无法知道传递了哪些参数。

如果您查看va_arg 宏和相关宏是如何实现的,您或许能够弄清楚如何检查堆栈中的所有内容。但是,这不是可移植的,除非作为调试辅助,否则不建议使用。

您可能还想研究变量参数的替代方法,例如函数重载、模板或传递 vectorlist 参数。

【讨论】:

  • 非常感谢您的建议。我试过你提到的方法。我遇到了这种方法的问题。 count 之后的第一个参数在 64 位 sles10 系统上总是得到垃圾值。 va_list 来自 .c 文件。经过一些基本检查后,va_list 被传递给 .cpp 文件。这就是垃圾问题出现的地方。在 .c 函数中,我做了 va_start(argp,App_Context *)。计数=va_arg(argp,int)。然后我调用 process(pActx,count,argp)。在它里面 va_arg(argp, type1)。因为 type1 总是得到垃圾值,我不得不改变方法。
【解决方案2】:

不,没有办法。 varargs 没有提供任何方法来检查传入的参数类型。您必须只使用正确的类型读取它们,这意味着您需要另一种方式来传达类型信息。

除非你真的需要,否则最好避免使用可变参数功能。它只是为了诸如printf 和朋友之类的遗留功能而真正的 C++ 功能。

【讨论】:

  • +1 这里的根本问题是main 是标准定义的类型不安全的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多