【发布时间】:2015-08-21 20:02:05
【问题描述】:
我一直在玩 C 中的类型转换。特别是,我一直(跟随 K&R)尝试实现一个程序,该程序将采用“一般”类型的输入(具体来说,K&R 实现了一个对指向通用数据的指针数组)。在这样做的过程中,我遇到了以下问题:
#include <stdio.h>
int comp(int *a, int *b); //*a == *b
main()
{
int a = 2;
int b = 3;
int *pa = &a;
int *pb = &b;
int (*pfunc)(void *, void *) = (int (*)(void *, void *)) comp;
int fin = (*pfunc)((void *)pa, (void *)pb);
printf("%d \n", fin);
}
这符合要求,并且可以满足您的期望。问题在于:
#include <stdio.h>
main()
{
int a = 2;
int b = 3;
int *pa = &a;
int *pb = &b;
void *pVoid_a = (void *) pa;
void *pVoid_b = (void *) pb;
int fin_Void = (*pVoid_a == *pVoid_b);
}
没用。
为什么这是一个问题:据我了解,在类型转换中
int (*pfunc)(void *, void *) = (int (*)(void *, void *)) comp;
创建了一个指针“comp”的副本,除了这个副本指向的函数接受参数“void *”而不是“int *”,并分配给变量“pfunc”。否则, pfunc 和 comp 的行为方式相同。 (我想我在这里一定是错的,但我不确定为什么)
在第一个程序中,当 (void *)pa 和 (void *)pb 被传递给 pfunc 时,我希望制作 pa 和 pb 的两个副本,但现在它们的类型是 (void *) 并分配给不同的名称。这些副本通过 pcomp 发送,打印返回的值等。
我试图在第二个程序中重新创建这个过程,但它不起作用!出于某种原因,在将 pVoid_a 和 pVoid_b 传递给 pfunc 之后的第一个程序中,它们最终在函数体中表现得像“int *”,即使它们似乎没有任何理由.为什么 pVoid_a 和 pVoid_b 在第一个程序中恢复了它们的“int”行为,而在第二个程序中没有?
【问题讨论】:
-
“复制了指针
comp”并不意味着“复制了它指向的函数”。它仍然调用原始函数,该函数仍然将其参数视为int*。 -
虽然这不是你的问题的原因,虽然它似乎有效,但将一个接受 int* 参数的函数转换为接受 void* 参数的函数是未定义的行为。
-
一般来说,与
qsort()等一起使用的比较器函数的可接受样式是函数进行指针转换,而不是调用者。也就是说,您将编写:int comp(const void *p1, const void *p2) { int i1 = *(int *)p1; int i2 = *(int *)p2; if (i1 < i2) return -1; else if (i1 > i2) return +1; else return 0; }并将这个准确键入的函数传递给qsort(),而无需进行任何强制转换。标准 C 库qsort()和bsearch()函数采用带有const void *参数的比较器。根据您的要求调整常数。 (这与 K&R 不同。)
标签: c function casting void-pointers