【问题标题】:C variadic function: How to specify which type to give to va_argC 可变参数函数:如何指定赋予 va_arg 的类型
【发布时间】:2015-02-13 12:33:59
【问题描述】:

在像 printf 这样的函数中,我们使用stdarg.h 来处理可变参数。

void print(int args,...){
    va_list ap;
    va_start(ap, args);
    int i = 0;
    for(i=0; i<args; i++){
        printf("%d\n",va_arg(ap, int));
    }
    va_end(ap);
}

我们想要解析格式列表(我们的可变参数函数的第一个参数)以跟踪格式列表中指定的参数的类型,然后使用适当的类型调用 va_arg。

我创建了第一个循环来解析格式列表,将说明符字母存储到一个数组中。 所以我知道我们期望哪种类型以及有多少。

例如:ft_like_printf("Watch your %d %s\n", 6, "Spider pig");

specifiers_list = "ds" 所以 d int 和 s char* (与 printf 相同的说明符)

但是如何动态地编码呢?使用不同类型调用 va_arg 的语法是什么?

我已经阅读了THISTHAT,我认为这正是我想要的,不是吗? 如果是,该怎么办?包含枚举+联合的结构或包含联合+函数指针的结构的真实案例场景是什么?

为了处理不同的数据类型,我从这个开始:

typedef struct s_flist
{
    char c;
    (*f)();
}              t_flist;

t_flist flist[] = 
    {
        { 's',  &putstr  },
        { 'i',  &put_number },
        { 'd',  &put_number }
    };

【问题讨论】:

  • 我不知道您所说的But how to code it dynamically? What is the syntax to call va_arg with differents types ? 是什么意思,我做过类似的事情,所以我可能会有所帮助,但我需要澄清一下。
  • 如果我们有 va_arg(ap, int),我们只能传递 int。那么如何使用 va_arg(ap, TYPE) 的 TYPE 等于当前参数的类型呢?
  • 没错,所以va_arg(ap, char *) 对应char * 等等。
  • 问题解决了吗?
  • 还没有。看,我不能为所有类型使用很多 ifs 或 switch case。相反,我必须使用我在帖子中展示的函数指针数组。我知道我必须将va_arg(ap, char *) 用于char * 等等,但是按照我想要的方式进行操作更复杂。我有 va_arg 的 2 个解决方案,在一个结构中,我将有一个函数指针 + 1) 一个 void * 2) 一个 union ,就像解释 HEREHERE 一样。还在想办法……

标签: c variadic-functions


【解决方案1】:

类型不是 C 中的一等公民。

但是您需要关心的类型并不多:您可以安全地从 unsigned 转换为 signed 或者反过来,char*void* 也是如此,所以对于基本的 printf ,你必须处理:

  • 字符
  • int
  • 浮动
  • 无效*

union 来救援!

typedef union
{
    char as_char;
    short as_short;
    int as_int;
    long as_long;
    float as_float;
    double as_double;
    void* as_ptr;
} t_value;

typedef enum {
    CHAR_T,
    INT_T,
    /* It goes on */
    ...
} t_type;

t_value get_value(va_list ap, t_type type) {
    /* You can't avoid this step, there is no way to iterate over types */
    switch (type) {
        case T_CHAR:
            return va_arg(ap, char);
        case T_INT:
            /* ... */
    }
}

然后你只需要创建一个查找表,为每个有效的格式说明符存储一个函数指针和一个t_type

【讨论】:

    猜你喜欢
    • 2015-05-27
    • 1970-01-01
    • 1970-01-01
    • 2012-08-20
    • 2011-02-19
    • 1970-01-01
    • 1970-01-01
    • 2011-03-25
    • 1970-01-01
    相关资源
    最近更新 更多