在C89中使用可变函数,而不需要传递参数或最后一个参数? [英] Use variadic functions in C89 without passing number of arguments or a final argument?

查看:253
本文介绍了在C89中使用可变函数,而不需要传递参数或最后一个参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个可变函数 foo(int tmp,...),当调用foo函数时,我需要知道有多少个参数。我知道有两种方法可以找出有多少参数:


  1. 在调用foo时使用最后一个参数,如-1,所以你的函数调用将是这样的: foo(tmp,1,2,9,-1)当你在foo里面,一个va_arg调用返回 - 1您知道您已阅读所有函数参数


  2. 在foo中再添加一个参数,程序员将拥有参数总数,因此您可以调用如下所示: foo(tmp,5,1,2,3,4,5) foo(tmp,2,7,8 )


我曾经遵循第一种方式,曾经遇到以下错误。使用代码:

  expr_of_type(expr,boolexpr_e,newtable_e,nil_e,-1)

其中expr_of_type是一个可变函数,并检查expr(第一个参数)是否是以下类型之一(boolexpr_e或new_table_e或nil_e都有枚举类型的类型)。
我偶然写道:

  expr_of_type(expr,boolexpr_e,newtable_e,nil_e -1)

我忘记了nil_e和-1之间的逗号,因为nil_e有枚举类型,nil_e - 1是一个有效的表达式,因为nil_e不是0给定的可变函数,当尝试获取expr_of_type参数没有找到-1作为最后的参数,并继续搜索创建一个错误,花了我一些时间找出。



我没有找到第二种方式,因为当从一个可变参数添加或删除一个参数时,需要更改包含总参数数的参数。



在寻找更好的方法来使用/创建可变属性函数时,我发现可变格宏这可以解决我使用第一种方式时遇到的错误。但可变的宏可用于C99标准。我正在寻找一种更好的方法来使用/创建C89中的可变参数。任何想法?

解决方案

一般来说,您仍然必须以某种方式传递参数,无论是通过哨兵值还是通过显式计数。



然而,您可以通过更好的哨点来修复您的哨兵问题。这是扩展为负常量的预处理器宏应该在括号中包围的原因之一:

  #define VARARG_SENTINEL(-1 )

然后 nil_e VARARG_SENTINEL 将生成一个编译错误



使用枚举 const int 将工作也是:

 枚举{VARARG_SENTINEL = -1}; 

对于其他原因,使用哨兵值的符号常量会更好(更多的自我记录,稍后更容易更改底层价值)。


Let's say I have a variadic function foo(int tmp, ...), when calling foo function I need to know how many arguments there are. I'm aware of two ways of finding out how many arguments there are:

  1. Use a final argument when calling foo, like -1, so your function call will be like this: foo(tmp, 1, 2, 9, -1) and when you are inside foo and a va_arg call returns -1 you know you have read all the function arguments

  2. Add one more argument in foo where the programmer will have the total number of arguments, so you will have calls to foo like this: foo(tmp, 5, 1, 2, 3, 4, 5) or foo(tmp, 2, 7, 8)

I used to follow the first way and once had the following bug. With the code:

expr_of_type(expr, boolexpr_e, newtable_e, nil_e, -1)

where expr_of_type was a variadic function and was checking if expr(the first argument) was one of the following types (boolexpr_e or new_table_e or nil_e had all type of an enumerated type). I one accidently wrote:

expr_of_type(expr, boolexpr_e, newtable_e, nil_e -1)

I forgot the comma between nil_e and -1, because nil_e had an enumerated type, nil_e - 1 was a valid expression and because nil_e was not 0 the given variadic function when trying to get expr_of_type arguments didn't find -1 as last argument and continued searching creating a bug which took me some time to find out.

I don't find the second way nice either, because when adding or removing one more argument from a variadic function you need to change the parameter that contains the number of total arguments.

In searching for a better way to use/create variadic functions I found variadic macros which can solve the bug I had when using the first way. But variadic macros are available to C99 standard. I was looking for a better way to use/create variadic functions in C89. Any ideas?

解决方案

In general, you must still pass along the argument count somehow, whether via a sentinel value or via an explicit count.

You could, however, fix your sentinel problem by making a better sentinel. This is one of the reasons why preprocessor macros that expand to negative constants should be surrounded in parentheses:

#define VARARG_SENTINEL (-1)

Then nil_e VARARG_SENTINEL will generate a compilation error.

Using enum or const int would work too:

enum { VARARG_SENTINEL = -1 };

Using a symbolic constant for the sentinel value would be better for other reasons too (more self-documenting, easier to change the underlying value later).

这篇关于在C89中使用可变函数,而不需要传递参数或最后一个参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆