我需要比较C中两个void
指针的值。在下面的代码中,我告诉控制台打印出它们是不同的。似乎比较是在这两个void
指针中包含的地址之间。
如何使代码比较1 == 1
指针的值(即:void
)并打印"same"
?
int main(void)
{
int i = 1;
int j = 1;
void *pi = &i;
void *pj = &j;
if (pi == pj) {
printf("same.\n");
} else {
printf("different.\n");
}
return 0;
}
答案 0 :(得分:3)
您必须知道void
指针真正指向的数据类型,强制指向该类型的指针,然后取消引用强制指针(并假设使用{{1}类型可比较类型}):
==
比较原始变量要容易得多:
if (*(int *)pi == *(int *)pj)
printf("same.\n");
else
printf("different.\n");
或使用正确键入的指针:
if (i == j)
…
在我不知道数据类型的情况下会发生什么(假设用户总是传递相同类型的数据以与我的链接列表删除方法进行比较)?
然后生活变得困难。理想情况下,程序员可以通过比较器函数 - 请参阅bsearch()
和
来自标准C库的qsort()
示例。
如果不这样做,您需要知道目标类型的大小,并希望int *pi = &i;
int *pj = &j;
if (*pi == *pj)
…
能够充分发挥作用。这远远不能保证 - 将两个memcmp()
值与double
进行比较将始终产生正确答案(例如,它可能声称NaN的不同表示形式不同)并不清楚将memcmp()
类型与填充进行比较是非常困难的,如果您通过节点,它对于您的链接列表数据类型将无法正常工作(如果您传递了数据,则可能没问题来自两个节点的字段)。
如果您需要进行排序而不仅仅是相等(例如二进制搜索树),则情况更糟 - 在这种情况下,需要程序员提供比较器功能。
答案 1 :(得分:2)
指针 不同。如果你试图比较指针指向的整数,那么你想要
if ( *(int*)pi == *(int*)pj ) {
答案 2 :(得分:1)
你必须输入转换void指针以输入int *
因为编译器不知道指针指向的是什么类型的地址,所以它不知道从指针地址读取多少字节并进行比较。试试这个
int i = 2;
int j = 1;
void *pi = &i;
void *pj = &j;
if ( (*(int*)(pi)) == (*(int*)(pj)) )
{
printf("same.\n");
} else
{
printf("different.\n");
}
return 0;
答案 3 :(得分:1)
根据您的评论,您尝试实现链接列表,并且不知道指针目标的数据类型。您的设计是错误的:使用void*
指针您根本无法(合理或可靠地)比较数据而不知道类型。你需要以不同的方式处理它。最好的方法是将链表实现为模板类。您的节点类看起来像
template <typename T> class Node
{
private:
T *m_pValue;
Node *m_prev;
Node *m_next;
...
}
但请注意,您需要非常小心内存管理。您需要决定谁将拥有和管理对象。在上面的类中,用户必须完全管理对象。如果您想减轻用户的负担,请使用自动打印机,这样您的节点就会变成
template <typename T> class Node
{
private:
std::auto_ptr<T> m_pValue;
Node *m_prev;
Node *m_next;
...
}
在这两种情况下,您都可以通过
比较这些值Node rhs, lhs;
*(lhs.m_pValue) == *(rhs.m_pValue);
这只是假设可以通过==来比较T类型,在大多数情况下应该是真的。
请注意,使用内存比较等建议只是危险的 - 这种比较完全忽略了底层数据类型的结构和语义。
好的,鉴于这必须在C中,请使您的节点像
struct node
{
void * m_pValue;
node * m_pPrev;
node * m_pNext;
}
并要求链表的用户必须为您提供指向比较器功能的指针
int (comparitor*)(void* lhs, void* rhs);
这正是Jonathan Leffler在下面提出的建议。究竟如何构建所有这些取决于你如何构建链表。