我有一个功能
void printMe (void *i)
{
printf("%d", i);
}
我想传递一个 void 指针并将其打印到屏幕上。如果 i 是整数、浮点数或双精度,则上面的示例很好,但如果 i 是字符,则崩溃。C 中没有像我通常在 C++ 中使用的重载。所以问题是这样的,我们是否可以在 C 中创建一个函数来打印它的参数元素,如果是的话,这怎么可能,因为此刻我完全无法理解。
我有一个功能
void printMe (void *i)
{
printf("%d", i);
}
我想传递一个 void 指针并将其打印到屏幕上。如果 i 是整数、浮点数或双精度,则上面的示例很好,但如果 i 是字符,则崩溃。C 中没有像我通常在 C++ 中使用的重载。所以问题是这样的,我们是否可以在 C 中创建一个函数来打印它的参数元素,如果是的话,这怎么可能,因为此刻我完全无法理解。
Q1:所以问题是这样的,我们可以在 C 中创建一个函数来打印它的参数元素吗?
答:不是你想要的方式。您必须将信息传递给函数,告诉它您传递的数据类型。
Q2:如果是的话,这怎么可能,因为此刻我完全无法理解。
A:它在躲避你,因为它做不到。没有与 void* 关联的元数据,编译器或运行时可以使用这些元数据来确定它们所指向的类型。你需要要么
正如代码所示,您可以在这里打印的唯一内容是 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){...}
首先,您打印的是指针,而不是它指向的内容。要打印实际内容,您需要传递*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 ... */
}
}
所以问题是这样的,我们可以在 C 中创建一个函数来打印它的参数元素吗?
我们可以。这样的函数已经是标准库的一部分——它被称为printf
;)
由于 C 中没有编译时函数重载,因此您必须以某种方式在运行时提供参数的类型。格式字符串可printf
用于执行此操作,因此当已经有可行的解决方案时,确实没有理由构建自己的包装函数。
如果您试图打印出指针值,正确的用法是printf("%p", i);
. “d”说明符用于整数,“p”用于指针。纠正这些是你的责任,如果你把它们混在一起,就会发生坏事。
我不知道为什么这对于 char * 而不是 int * 会失败,并且您可能还有其他问题导致了这种情况。如果它仍然因 %p 而失败,则其他事情搞砸了。看看您是否可以安装某种内存监控软件来检查悬空指针或双重 free(),因为那时聪明的钱就是您在某处损坏了内存。