我正在开发一个自定义LISP解释器。它不支持像LISP中那样定义函数,而是将所有函数映射到C函数。当它看到像<,p>这样的表达式时
(substr 'input '1 '1)
它知道调用内部substr
函数并返回结果。
现在我计划实现一个支持基本格式化的message
函数,并将输出写入stdout
。像,
(message "Hello, %s" name)
%s
将替换为变量name
中的值。
目前的计划是直接将格式和参数传递给printf
等函数。这样,我就可以支持printf
支持的所有格式。但问题来自可变数量的参数。一种方法是,
if(argcount == 1)
/* call printf with one arg */
else if(argcount == 2)
/* call printf with two arg */
....
这有效,但我想知道有没有更好的方法来实现这一目标?
答案 0 :(得分:2)
我怀疑有办法做到这一点。原因是lisp函数的参数数量仅在运行时已知,但在编译时必须知道C函数的参数数量。
这包括va_lists,除非你想以某种特定于平台的方式攻击它们。
你真正做的最好的事情就是在C中编写一个函数,它能够一次循环一个参数并对它们做一些事情。我能看到的唯一方法是不仅为每个内部函数存储一个函数指针,而且还存储一个“调用约定”,它将提供有关它是以普通方式获取参数还是以其完成的信息。相当于一个va_list。
像printf这样的函数会有一个包装器,printf_wrapper,比如说,你可以存储一个包装器的函数指针。此包装器将接受格式字符串作为普通参数,后跟其他参数的列表或数组(大致类似于va_list)。
您可能指示printf_wrapper与通过指定调用约定为printf_wrapper函数为“va_list_type”期望列表的参数完成的,这意味着它需要通常的固定参数,并且所有其余的参数必须被捆绑起来并供给把它当作一个清单。
当然,编写一个printf_wrapper函数可以将格式字符串拆分并解析为多个格式字符串,这有点工作。这是一个我正好做到这一点的例子,以便我可以添加自己的自定义格式说明符:
答案 1 :(得分:0)
让你的C函数采用类似argc/argv
的参数。也就是说,取一个参数指定参数的数量,然后指向每个参数的指针列表。
答案 2 :(得分:0)
稍微好于 if-else 链是一个开关。
switch(argcount){
case 1: printf(arg[0]); break;
case 2: printf(arg[0],arg[1]); break;
//etc.
}