【问题标题】:How do I access a specific argument without knowing it's type [variable arguments] in C?如何在不知道 C 中的类型 [变量参数] 的情况下访问特定参数?
【发布时间】:2017-06-10 20:17:11
【问题描述】:

好的,所以我正在编写一个日志服务,它将一些数据写入某个文件(假设文件的名称是 log)。

我要写入的数据类型不同,可能是 int 或 string 或其他。

到目前为止,这是我的函数的外观:

void write_log(FILE * fp, char * event, ...)
{
    va_list list;
    va_start(list, event);
    // Cannot use va_arg(list, type_of_var) here!!!
}

我调用函数的方式可能因我的数据而异:

write_log(fp, "Memory size :", mem_size);

或者

write_log(fp, "Username :", username);

我不知道第三个参数是字符串还是 int 或其他。

我本可以使用va_arg(list, type_of_var),但由于我的数据类型任意变化,我无法使用它。

知道如何在不知道函数类型的情况下访问函数的第三个参数吗?

【问题讨论】:

  • 你不能。为什么你认为像 printf 这样的函数需要格式字符串?
  • 对我的功能有什么想法或解决方法吗?
  • 一种解决方法:使用所需字段定义 struct,并将其传递给写入文件的函数。该函数从结构中读取相关数据并将它们写入您的日志。
  • @Dan 不幸的是,我目前仅限于 C。
  • This example of _Generic 是 C 解决方案的开始。主要思想是使用_Generic 也传递一个值来指示如何处理 ... 参数。

标签: c arguments type-conversion


【解决方案1】:

没有可移植的标准方法来了解类型是什么。

想到的第一个解决方案是使用众所周知的 C 习惯用法,即必须传递格式字符串(例如 printfscanf)。

void write_log(FILE * fp, char * event, const char* fmt, ...)
{
    va_list list;
    va_start(list, event);

    // process fmt and act accordingly
}

如果它只是一个额外的参数,那么你可以传递一个enum

enum type {
   integer,
   pointer,
   floating
};

void write_log(FILE * fp, char * event, enum type t, ...)
{
    switch(t)
    {
    case integer: // do stuff with integer
    case pointer: // do stuff with pointer
    }
}

如果您可以访问 C11 的 _Generic 功能,就像大多数现代编译器所做的那样,您可以拥有类似的东西:

void write_logi(FILE * fp, char * event, int);
void write_logf(FILE * fp, char * event, float);
void write_logfoo(FILE * fp, char * event, struct foo);

#define write_log(file, event, arg) _Generic((arg), \
    int: write_logi,                                \
    float: write_logf,                              \
    struct foo: write_logfoo                        \
)(file, event, arg)

那么你可以调用为:

write_log(fp, event, i/*int*/);
write_log(fp, event, f/*float*/);

并选择适当的功能。

【讨论】:

  • UV for _Generic 这是一种可移植的 C11 方法来了解类型是什么,尽管仅限于预先定义的集合。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-13
  • 1970-01-01
  • 1970-01-01
  • 2020-03-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多