来自椭圆的va_list如何与 vfprintf() 调用交互
How does a va_list from an ellipses interact with a vfprintf() call?
我正在努力修补一些旧代码(15-20 岁),我不时会遇到奇怪的片段。 这是一个让我挠头的问题。
27 void FormDefFileScanner::FormDefFileerror(char *fmt, ...)
28 {
29 va_list va;
30 va_start(va, fmt);
31 /* This is related to some sort of debuging */
32 if (FormDefFilelineno)
33 fprintf(stderr, "%d: ", FormDefFilelineno);
34 /* This is where I'm unsure */
35 (void) vfprintf(stderr, fmt, va);
36 fputc('n', stderr);
37 va_end(va);
... /* rest of the program */
... }
我从我对"......"的研究中知道。争论va_list应该如何工作。 我的意思是需要具有列表和变量类型的 va_arg() 调用才能从va_list中正确提取值。 我想我想知道 vprintf() 调用如何正确解析va_list。 我认为格式字符串有帮助,但我不确定va_list中的每个内容都具有相同的单词大小。 任何见解将不胜感激。
让我们玩"想象力"。 想象一下这样的代码:
typedef char* va_list;
#define va_start(va_bytes, arg) (va_bytes=reinterpret_cast<char*>((&arg)+1))
#define va_end(va_bytes)
#define va_arg(va_bytes,type) (*reinterpret_cast<type*>((va_bytes+=sizeof(type))-sizeof(type)))
所以你的代码变成这样:
void FormDefFileScanner::FormDefFileerror(char *fmt, ...)
{
char* va_bytes;
va_bytes = reinterpret_cast<char*>((&fmt)+1); //points at first byte of ...
vfprintf(stderr, fmt, va_bytes); //passes a pointer to the bytes to vfprintf.
然后 vprintf 可以做到这一点:
void vfprintf(FILE*, char* format, char* va_bytes)
{
if (strcmp(format,"%d")==0) { //now we know the first param is an int
//I'm splitting the macro into two lines here for clarity
int value = *reinterpret_cast<int*>(va_bytes);
va_bytes += sizeof(int); //va_bytes now points at the second parameter
} else if (strcmp(format,"%llu")==0) { //first param is an long long unsigned int
//I'm splitting the macro into two lines here for clarity
long long unsigned value = *reinterpret_cast<long long unsigned*>(va_bytes);
va_bytes += sizeof(long long unsigned); //va_bytes now points at the second parameter
}
在任何时候,va_bytes指向下一个参数的开头。 当给定一个va_arg
时,它会将这些字节转换为该类型,并将指针前进到紧随其后,这是后续参数的开始。 在你通过va_arg
告诉它类型之前,它不能前进,因为它不知道类型,因此它不知道每个参数中有多少字节。
真正的宏va_arg
要复杂得多,因为它处理类型对齐等,vfprintf
显然不像我编码的那样工作,但这些应该有助于澄清一般概念。
我想我想知道
vprintf()
调用如何正确解析va_list
.我假设格式字符串有帮助,但我不确定每个va_list
中的事物具有相同的单词大小。
va_list
中的事物没有相同的大小。 vprintf
不必手动"解析va_list
"——它可以使用va_arg
。它知道下一个参数需要是什么类型,因为格式字符串中的格式说明符。所以你可以想象,如果你在解析格式字符串的循环中编写vprintf
,你会为每个格式说明符提供大小写,然后在每种情况下,它们都会使用 va_arg
来获取正确类型的下一个参数:
if (strcmp(format,"%d")==0) {
int value = va_arg(va, int);
// do stuff ...
} else if (strcmp(format,"%f")==0) {
double value = va_arg(va, double);
// do stuff ...
}
//...
至于如何实现va_list
,va_arg
等,那是不透明的,你不应该关心,因为它因架构和系统而异。你只需要知道,如果你遵守va_start
、va_arg
等的合同,它就可以了。
- Qt VTK交互风格的信号到小部件
- Qt Quick-如何仅从c++代码与qml属性交互
- 复制和交换习惯用法与移动操作之间的交互
- 为什么在访问 vtkRenderWindow 的"交互器"变量时会发生段错误?
- Qt QGraphicsProxyWidget 与 QGraphicsScene 的交互
- 使用 Python 事件并与 C++ 交互
- 函数-本地枚举声明和 ADL 的交互
- 如何在扩展的QQuickItem中与模型交互
- 寻找C++中数组和cout交互的解决方案
- C++继承和"常量"交互的问题
- 以太坊与外部 c++ 库的交互稳定性
- 玩家移动和碰撞之间的交互问题
- C++ 和 Lua 函数之间的交互与 3D 矢量参数
- 内存分配究竟是如何发生的,Java和C如何交互以跟踪同一对象?
- 如何包装对象,使它们成为无法交互的单独类型?
- 通过交互器获取向量中的索引
- 如何在python中的PyArrow和C++中的Arrow之间进行交互时将PyArrow表转换为Arrow表
- 检测屏幕上的坐标是否可交互
- 如何在不中断整个循环的情况下跳过循环交互 - C++
- 来自椭圆的va_list如何与 vfprintf() 调用交互