c - 使用 void* 指针将未知/混合类型传递给 printf() (一种在运行时推断类型)

标签 c pointers casting printf

我正在尝试将混合类型传递给 printf()。在实际代码中(底部),我还传递了格式占位符,以便 printf() 知道如何格式化。

当我不小心直接使用这些 void* 指针作为值调用时,我发现我的代码没有按预期工作。

所以我创建了一个测试程序,进行了搜索和探索,直到我想出了这个解决方案。

#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

void test1(void* a) {
    printf("value: %d\n", *(int*)a);
}

void test2(void* a) {
    printf("value: %f\n", *(float*)a);
}

int main(int argc, char** argv) {
    int* aip = &(int){1};
    test1(aip);

    int ai = 1;
    test1(&ai);

    float af = 1.75;
    test2(&af);

    return 0;
}

但我不想硬编码 *(int*)*(float*) 取消引用和强制转换,但实际上是这样写的:

void test(void* a) {
    printf("value: %VARIES\n", a);
}

VARIES 被传递到 test() 并连接到最终的格式化程序字符串中。

实际的功能是这样的:

void fn(void* value, char* fmtChar) {
    char fmtHelper[50];
    // fill fmtChar in formatter string's %s placeholder
    snprintf(fmtHelper, sizeof(fmtHelper), "value : %s\n", fmtChar);
    // actually print value varying argument
    printf(fmtHelper, value);   
}

我当前的解决方法是使用 switch/case 语句并以编程方式确定转换和格式化程序占位符。

最佳答案

如果你的目标是当前的 C (C11),你可以使用带有宏的泛型表达式来创建泛型函数:

#include <stdio.h>

void print_int(int x) {
    printf("an int: %d\n", x);
}

void print_double(double x) {
    printf("a double: %f\n", x);
}

#define print(X) _Generic((X),             \
                     float: print_double,  \
                     double: print_double, \
                     default: print_int    \
                 )(X)

int main(void) {
    print(1);   // an int: 1
    print(1.0); // a double: 1.00000
}

关于c - 使用 void* 指针将未知/混合类型传递给 printf() (一种在运行时推断类型),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37260030/

相关文章:

c++ - 簿记 vs 使用指针检查成员变量是否已初始化

c - 将地址传递给指针是否会导致类型提升

c++ - 在 c++ 中从 long long 转换为 int 和其他方式

c++ - GStreamer 管道在 gst_element_get_state 上挂起

C 线程无效读取大小为 8 的缓冲区数组

c - 双向链表 - 合并排序后更新列表->尾部

c++ - 什么时候在 C++ 中解析函数模板?

python - 如何在 Python 中检测字符串并将其转换回正确的类型

c# - C# 中的转换和性能

c - 读取文件时内存分配问题