Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/136.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
我可以从变量参数函数中提前返回吗? 假设我有两个C++函数用于调试输出: void Trace( const wchar_t* format, ... ) { va_list args; va_start( args, format ); VarArgTrace( format, args ); va_end( args ); } void VarArgTrace( const wchar_t* format, va_list args ) { WCHAR buffer[1024]; //use ::_vsnwprintf_s to format the string ::OutputDebugStringW( buffer ); }_C++_Visual C++_Variadic Functions - Fatal编程技术网

我可以从变量参数函数中提前返回吗? 假设我有两个C++函数用于调试输出: void Trace( const wchar_t* format, ... ) { va_list args; va_start( args, format ); VarArgTrace( format, args ); va_end( args ); } void VarArgTrace( const wchar_t* format, va_list args ) { WCHAR buffer[1024]; //use ::_vsnwprintf_s to format the string ::OutputDebugStringW( buffer ); }

我可以从变量参数函数中提前返回吗? 假设我有两个C++函数用于调试输出: void Trace( const wchar_t* format, ... ) { va_list args; va_start( args, format ); VarArgTrace( format, args ); va_end( args ); } void VarArgTrace( const wchar_t* format, va_list args ) { WCHAR buffer[1024]; //use ::_vsnwprintf_s to format the string ::OutputDebugStringW( buffer ); },c++,visual-c++,variadic-functions,C++,Visual C++,Variadic Functions,上面使用的是Win32OutputDebugStringW(),但这并不重要。现在,我想优化格式,以便在没有调试器的情况下,不会执行附加的格式设置(我测量到-加速非常重要): 如果我提前返回一次IsDebuggerPresent()返回null,除了跳过格式化之外,是否会影响其他任何事情 我的意思是我不再叫va_start和va_end-这有关系吗?跳过va_start和va_end是否会导致任何意外的行为更改?所有这些宏(至少在Windows上)都是对参数列表中书签的指针操作。早点回来就好了。

上面使用的是Win32
OutputDebugStringW()
,但这并不重要。现在,我想优化格式,以便在没有调试器的情况下,不会执行附加的格式设置(我测量到-加速非常重要):

如果我提前返回一次
IsDebuggerPresent()
返回null,除了跳过格式化之外,是否会影响其他任何事情

我的意思是我不再叫
va_start
va_end
-这有关系吗?跳过
va_start
va_end
是否会导致任何意外的行为更改?

所有这些宏(至少在Windows上)都是对参数列表中书签的指针操作。早点回来就好了。这是特定于编译器的,尽管我无法想象为什么早期返回在其他平台上会是一个问题

从x86
vadefs.h

#define _crt_va_start(ap,v)  ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) )
#define _crt_va_arg(ap,t)    ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
#define _crt_va_end(ap)      ( ap = (va_list)0 )

不,没有义务在varargs函数中使用va_start


如果不使用va_start,则无法使用va_end;如果使用va_start,则应使用va_end,无论函数如何返回。

提前返回的唯一要求是,如果已使用(执行)
va_start()
,则必须在返回之前使用
va_end()

如果你藐视这条规则,你会在大多数系统上逃脱惩罚,但是有些系统需要
va_end()
,所以不要冒险忽略它。省略它是未定义的行为


除此之外,如何处理报税表取决于您。您建议的提前返回不是问题。

这是非常安全的,因为在C语言中,“清除”堆栈中传递的参数的工作总是由调用函数完成,而不是被调用函数


有些语言(我想到帕斯卡语)可能会反过来做。这可能会更有效,但之所以有效,是因为没有可变参数数的概念。

varargs的内容没有太多开销,通常只是一些指针操作。 在设置每个varargs调用的堆栈时,可能会有稍多的开销,因此

void Trace( const wchar_t* format, ... ) { if( !IsDebuggerPresent() ) { return; } //proceed as previously va_list args; ..... } 无效跟踪(常量wchar\u t*格式,…) { 如果(!IsDebuggerPresent()){ 返回; } //照旧进行 va_列表参数; ..... } 您最好使用预处理器来防止在非调试构建中调用跟踪内容

乱扔代码

if( IsDebuggerPresent() ) Trace( stuff... ); if(IsDebuggerPresent())跟踪(stuff…); 看起来也很讨厌


VC2010获得可变宏了吗?:)

我认为这样的想法是,如果某个调用约定是受虐狂,足以以复杂的方式传递varargs,那么
va_start
实际上可能会解析出一些东西。C基本原理文档曾经说过,“对象可能包括指向由va_start宏分配并由va_end宏销毁的内存的指针”。实际上,我遇到过的最糟糕的情况是在ARM上实现varargs宏,调用约定是
long-long
double
是8对齐的。所以
va_arg
不得不跳过填充,但是
va_end
仍然没有做任何事情;除了varargs之外,在一些平台上,被调用方在C中清理堆栈。 if( IsDebuggerPresent() ) Trace( stuff... );