c++ - 获取没有初始参数的省略号函数参数

标签 c++ parsing variadic-functions

所以我一直在为脚本语言制作一个自定义解析器,并且我希望能够仅传递省略号参数。我不需要也不想要初始变量,但是 Microsoft 和 C 似乎想要其他东西。仅供引用,请参阅底部的信息。

我查看了 va_* 定义

#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 )

我不想要的部分是 va_start 中的 v 。作为一个小背景,我擅长 goasm 并且我知道堆栈是如何工作的,所以我知道这里发生了什么。我想知道是否有一种方法无需使用内联汇编即可获取函数堆栈基数。

我的想法:

#define im_va_start(ap) (__asm { mov [ap], ebp })

等等......但我真的觉得这很困惑,而且我做错了。

struct function_table {
    const char* fname;
    (void)(*fptr)(...);
    unsigned char maxArgs;
};
function_table mytable[] = {
{ "MessageBox", &tMessageBoxA, 4 } };

...某个函数对传递给它的 const char* 进行排序,以在 mytable 中查找匹配的函数,并使用参数调用 tMessageBoxA。另外, maxArgs 参数只是为了让我可以检查是否发送了有效数量的参数。我有个人原因不想在函数中发送它,但同时我们可以说这是因为我很好奇。

这只是一个例子;自定义库是我要实现的,因此它不仅仅是调用 WinAPI 的东西。

void tMessageBoxA(...) {
// stuff to load args passed
MessageBoxA(arg1, arg2, arg3, arg4);
}

我正在使用 __cdecl 调用约定,并且我已经查找了可靠地获取指向堆栈底部(而不是顶部)的指针的方法,但我似乎找不到任何方法。另外,我不担心函数安全或类型检查。


编辑:感谢您的输入,看来这是不可能的。

我的修复最终是

    #define im_va_start(ap) {\
        __asm push eax\
        __asm mov eax, ebp\
        __asm add eax, 8h\
        __asm mov ap, eax\
        __asm pop eax\
    }

然后我就可以照常继续。

至于为什么我需要它,我正在做一些(独特的)read: unsafe 技巧,并使用带有指向上面定义的函数的指针的结构数组。由于每个函数都是唯一的,并且大多数函数都来 self 的自定义库,因此它们具有......不同的行为。我真的不知道如何解释,但是当我完成 POC 时我会发布源代码。

我并不真正担心可移植性,所以这必须起作用。另外,为了计算我所做的参数:

#define im_va_count(ap, num, t) {\
for(num = 0; *(t*)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) > 0; ++num){ }\
--num;\
im_va_start(argptr);\
}

这对我有用。如果有人有兴趣...

最佳答案

不幸的是,这是不可能的,C 标准说:

A function may be called with a variable number of arguments of varying types. As described in 6.9.1, its parameter list contains one or more parameters.

并且 ... 不算“一个或多个参数”。此外,

The va_start macro shall be invoked before any access to the unnamed arguments.

它应该被称为

va_start(va_list, parmN)

还有那个

The parameter parmN is the identifier of the rightmost parameter in the variable parameter list in the function definition (the one just before the , ...).

因此,正如您所看到的,在标准 C++ 中,在省略号之前不能有一个没有至少一个参数的可变参数函数。非可移植组装技巧是您能想到的最接近的技巧。

关于c++ - 获取没有初始参数的省略号函数参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13097167/

相关文章:

C - 在可变函数中将多个函数地址作为参数传递

c++ - 如何取字符串的反转

java - 用java解析apache tomcat accesslog

c++ - 在 C++ 中缓存浮点值

python - 我们如何在 python 中解析包含带有 xml 命名空间标签的节点的 xml 数据?

java - 解析可变行数

c++ - fscanf 的包装功能不起作用

c++ - 不使用 << 的带有值的 QVector 的单行实例化

C++ const char* 在方法调用中带有字符串文字

c++ - 在 C++ 中导入/包含所有库的快捷方式