我有一个关于重新启动可变参数列表(va_list)的问题.基本上我想做这样的事情:
void someFunc(char* fmt, ...) {
va_list ap;
va_start(fmt, ap);
otherFuncA(fmt, ap);
// restart ap
otherFuncB(fmt, ap);
// restart ap
...
va_end(ap);
return;
}
Run Code Online (Sandbox Code Playgroud)
现在我的问题是:如何重启ap?
请注意,这个问题与C++无关,但是C.
到目前为止,我找到了两种可能的解决方案,但我想知道哪一种是"正确的"或"最佳实践".
解决方案1:多重 va_start()
使用GCC7我可以替换线路
// restart ap
Run Code Online (Sandbox Code Playgroud)
在上面的例子中
va_end(ap);
va_start(fmt, ap);
Run Code Online (Sandbox Code Playgroud)
重置ap为第一个参数.但是,我不确定这是否真的是有效的代码,或者我很幸运,一些未定义的行为没有破坏结果.
解决方案2: va_copy()
另一个适用于GCC7的解决方案是初始化几个ap使用va_copy()类似的副本
void someFunc(char* fmt, ...) {
va_list ap1, ap2;
va_start(fmt, ap1);
va_copy(ap2, ap1);
otherFuncA(fmt, ap1);
otherFuncB(fmt, ap2);
va_end(ap1);
va_end(ap2);
return;
}
Run Code Online (Sandbox Code Playgroud)
这是有效的代码(imo),但由于现在有多个va_list实例需要复制,因此效率远低于第一个解决方案.
那么哪种解决方案最好?它是我上面提到的两个中的一个,还是完全不同的东西?
我希望这个问题已经被回答了上千次,但是我只是无法找到解决问题的方法=(
我想在LaTeX(TikZ)中计算一些值,其中一些是长度(例如10 pt),有些则不是。只要计算形式非常简单,就像a*b+c一切都很好,但是如果我需要像(a+b)*(c+d)LaTeX 这样的括号,就会抱怨。此外,如果我有嵌套定义,则无法按预期解决这些问题。例:
\def\varA{1+2}
\def\varB{10}
% I want to calculate (1+2)*10 or 10*(1+2), respectively.
\def\varC{\varA*\varB} % evaluates to 21
\def\varD{\varB*\varA} % evaluates to 12
Run Code Online (Sandbox Code Playgroud)
所以基本上我的问题是:在LaTeX中进行计算的正确(或推荐)方法是什么?
作为一个更现实的示例,这是我实际上想要做的,但不能做的:
% total height of my TikZ image
\def\myheight{20ex}
% five nodes shall be drawn as a stack
\def\numnodes{5}
% but there shall be some space at the top (like a 6th node)
\def\heightpernodeA{\myheight / (\numnodes + 1)} % fails whenever I want to use it
% workaround?
\def\numnodesplusone{\numnodes …Run Code Online (Sandbox Code Playgroud) 这个问题是关于使用函数指针,它不完全兼容,但我希望我可以使用它,只要我的代码只依赖于兼容的部分。让我们从一些代码开始来了解这个想法:
typedef void (*funcp)(int* val);
static void myFuncA(int* val) {
*val *= 2;
return;
}
static int myFuncB(int* val) {
*val *= 2;
return *val;
}
int main(void) {
funcp f = NULL;
int v = 2;
f = myFuncA;
f(&v);
// now v is 4
// explicit cast so the compiler will not complain
f = (funcp)myFuncB;
f(&v);
// now v is 8
return 0;
}
Run Code Online (Sandbox Code Playgroud)
虽然参数myFuncA和myFuncB相同且完全兼容,返回值不并因此仅仅通过调用代码忽略。我尝试了上面的代码,它使用 GCC 可以正常工作。