【问题标题】:Print void type in pure C在纯 C 中打印 void 类型
【发布时间】:2010-10-03 17:21:09
【问题描述】:

我有一个类似的功能

void printMe (void *i)
{
    printf("%d", i);
}

我想传递一个 void 指针并将其打印到屏幕上。 如果 i 是整数、浮点数或双精度,则上面的示例很好,但如果 i 是字符则崩溃。 C 中没有像我通常在 C++ 中使用的重载。 所以问题是这样的,我们是否可以在 C 中创建一个函数来打印它的参数元素,如果是的话,这怎么可能,因为此时我完全无法理解。

【问题讨论】:

  • 这个问题似乎很困惑——无论你做什么,提供的示例都会打印指针值——指针指向 char、int 还是 double 都没有关系。 “如果 i 是整数”是指指向整数的指针,还是将整数转换为指针?更完整的代码示例可能会有所帮助。

标签: c printf type-conversion void


【解决方案1】:

如果你试图打印出指针值,正确的用法是printf("%p", i);。 “d”说明符用于整数,“p”用于指针。正确处理这些是你的责任,如果你把它们混在一起,就会发生坏事。

我不知道为什么这对于 char * 而不是 int * 会失败,并且您可能还有其他问题导致了这种情况。如果它仍然以 %p 失败,则其他事情搞砸了。看看你是否可以安装某种内存监控软件来检查悬空指针或双重 free(),因为那时聪明的钱就是你在某处损坏了内存。

【讨论】:

    【解决方案2】:

    Q1:所以问题是这样的,我们可以在 C 中创建一个函数来打印它的参数元素

    A:不是你想要的方式。您必须将信息传递给函数,告诉它您传递的数据类型。

    Q2:如果是的话,这怎么可能,因为此刻我完全无法理解。

    A:它正在逃避你,因为它无法完成。没有与 void* 关联的元数据,编译器或运行时可以使用这些元数据来确定它们所指向的类型。你需要

    1. 传递一个包含一个
      的结构 关于什么的指针和信息
      指针指向(例如 枚举)。
    2. 传递一个额外的参数 关于指针的信息 指向

    就代码而言,您可以在这里打印的唯一内容是 i 指向的地址。

    空指针指向原始数据,printf 假定您知道要打印的数据类型,它没有智能并且无法为您“弄清楚”。

    就这么简单。

    你可以做的是将类型信息传递给函数,但你最终会得到非常类似于 printf 它本身的东西,你传递一个格式化字符串,其中包含有关以下参数中数据的类型信息。

    希望这会有所帮助。

    还有。 . . "C 中没有我通常在 C++ 中使用的重载"

    即使在 c++ 中,重载也是在编译时发生的,编译器无法知道将哪些数据传递给该函数,因此即使您习惯于重载,它也永远不会像这样工作(例如使用 printf 尝试同样的事情,但使用 C++ 编译器编译它,你会得到完全相同的结果)。 实际试试

    cout << i;
    

    在上面的函数中,它会给你 i 指向的地址,而不是 i 的“值”。 在获得它的价值之前,您需要先转换 i 并对其加以尊重

    cout << *(int*)i;
    

    因此,要使上述内容在 C++ 中工作,您需要有很多重载函数(或模板函数,这实际上是一回事,除了编译器会为您滚动函数),例如重载函数

    printMe(int i){...}
    printMe(double d){...}
    printMe(char c){...}
    printMe(char* string){...}
    

    在 c 中,您只需为这些函数指定特定名称

    printInt(int i){...}
    printDouble(double d){...}
    printChar(char c){...}
    printString(char* string){...}
    

    【讨论】:

    • 如果您觉得自己倾向于使用宏技巧:#define printMe(x,y) print##x(y) 用作:printMe(Int,pippo); printMe(Char,冥王星);与原始版本相比没有真正的好处,只是可以假装它只使用一个函数“printMe()”。
    • 小心,因为据我所知,这些宏技巧是特定于供应商的(准确地说是 MS)。如果我错了,有人可以添加评论吗?谢谢
    • ## 连接运算符是基本 C 预处理器规范的一部分。
    • 也很少有使用这些宏技巧构建的库——假装函数重载。例如,值得一看 tgmath.h ...
    【解决方案3】:

    首先,您打印的是指针,而不是它指向的内容。要打印实际内容,您需要将*i 传递给printf,而不是i

    如果你真的想这样做,一个解决方案是:

    void printMe (void *p, int typ) {
        switch(typ) {
            case TYP_INT: printf("%d", *((int*)p)); break;
            case TYP_CHR: printf("%c", *((char*)p)); break;
            /* and so on ... */
        }
    }
    

    【讨论】:

    • 嗯,这取决于您作为第一个参数传递给 printf 的内容。如果您传递 %s,它将尝试打印 void 指针指向的内容。
    • ...但实际上我明白你在说什么,这在问题的背景下是有道理的。原谅我,我还没完全清醒……
    【解决方案4】:

    所以问题是这样的,我们可以在 C 中创建一个函数来打印作为参数的元素

    是的,我们可以。这样的函数已经是标准库的一部分——它被称为printf ;)

    由于 C 中没有编译时函数重载,因此您必须以某种方式在运行时提供参数的类型。 printf 格式字符串可用于执行此操作,因此当已经有可行的解决方案时,真的没有理由构建自己的包装函数。

    【讨论】:

    • 是的,但我的问题是我不知道在运行时间之前我会是什么,所以我宣布它无效 *。直到现在都没有答案
    • 我对你的评论感到困惑:printf 已经可以接受任何类型的参数;在调用您可能自己实现的任何打印函数之前,没有办法知道变量的类型:还有什么办法知道如何打印值?
    猜你喜欢
    • 1970-01-01
    • 2021-06-13
    • 2019-07-21
    • 1970-01-01
    • 2023-03-26
    • 1970-01-01
    • 2019-05-26
    相关资源
    最近更新 更多