简体   繁体   English

C可变参数函数:如何指定要赋予va_arg的类型

[英]C variadic function: How to specify which type to give to va_arg

In a function like printf, we use stdarg.h to handle the variadic parameters. 在类似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);
}

We want to parse the format list (the first argument given to our variadic function) to track the types of the arguments specified in the format list then, call va_arg with the appropriate type. 我们想解析格式列表(给可变参数函数的第一个参数),以跟踪格式列表中指定的参数类型,然后用适当的类型调用va_arg。

I make a first loop to parse the format list, store the specifiers letters into an array. 我进行第一个循环以分析格式列表,将说明字母存储到数组中。 So I know which type we expect and how many there is. 所以我知道我们期望哪种类型,以及有多少种。

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

specifiers_list = "ds" So d <=> int and s <=> char* (same specifiers as printf) specifiers_list = "ds"所以d <=> int和s <=> char *(与printf相同的说明符)

But how to code it dynamically ? 但是如何动态编码呢? What is the syntax to call va_arg with differents types ? 用differents类型调用va_arg的语法是什么?

I have read THIS and THAT which I think are what I'm looking for, aren't they ? 我已阅读THAT我认为是什么我要找的,不是吗? If yes, what to do with it ? 如果是,该怎么办? What are the real case scenarios of a struc containing an enum + union or struct containing an union + function pointer ? 包含枚举+联合的结构或包含联合+函数指针的结构的实际情况是什么?

To handle the different data types, I had started with this: 为了处理不同的数据类型,我从这里开始:

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

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

Types are not first-class citizens in C. 类型不是C语言中的一等公民。

But there are not that many types you have to care about: you can safely cast from unsigned to signed and the other way around, same goes for char* and void* , so for a basic printf, you have to handle: 但是,您不必担心很多类型:您可以安全地将类型从unsignedsigned ,反之亦然, char*void*也是如此,因此对于基本的printf,您必须处理:

  • char 烧焦
  • short
  • int 整型
  • long
  • float 浮动
  • double
  • void* 无效*

union to the rescue ! 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:
            /* ... */
    }
}

Then you just have to create a lookup table, storing both a function pointer and a t_type for each valid format specifier. 然后,您只需要创建一个查找表, t_type为每个有效格式说明符存储一个函数指针和一个t_type

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM