8

我有一个功能

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

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

4

4 回答 4

25

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

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

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

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

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

正如代码所示,您可以在这里打印的唯一内容是 i 指向的地址。

一个 void 指针指向原始数据, 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){...}
于 2009-01-27T09:25:32.367 回答
8

首先,您打印的是指针,而不是它指向的内容。要打印实际内容,您需要传递*iprintf,而不是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 ... */
    }
}
于 2009-01-27T09:30:27.053 回答
0

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

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

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

于 2009-01-27T09:36:20.910 回答
0

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

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

于 2009-01-27T15:03:49.280 回答