将32位int转换为64 void *指针而不发出警告

时间:2011-09-12 18:48:05

标签: c 64-bit void-pointers

我在C中有一个“通用”链接链接,它使void * data将数据存储在节点中。

insertNode(linkedList * list, void *data);

//Storing/retrieving a string works fine;
char *str="test"; 
insertNode(list, str);
char *getback=(char *)node->data;

//Storing/retrieving an Int results a cast warning
int num=1;
insertNode(list,(void *)num);
int getback=(int)node->data;

这是因为int是32位,但x64计算机上void *是64位。摆脱这个错误的最佳做法是什么?

4 个答案:

答案 0 :(得分:13)

使用intptr_tuintptr_t。它们是与指针大小相同的整数:

#include <stdint.h>
...
intptr_t num = 1;
insertNode(list, (void *) num);
intptr_t getback = (intptr_t) node->data;

当然,您可以存储的最大值取决于系统,但您可以在编译时通过INTPTR_MININTPTR_MAX进行检查。

答案 1 :(得分:2)

使用void *成员来存储整数值并不是一个很好的做法 - 除了其他任何东西之外,不能保证以这种方式可存储的整数范围。如果要在结构中存储指针或整数,那么您应该使用的是union

union data {
    void *p;
    int i;
};

insertNode(linkedList * list, union data data);

// Storing/retrieving a string:
char *str="test"; 
union data d;
d.p = str;
insertNode(list, d);
char *getback = node->data.p;

// Storing/retrieving an int:
int num = 1;
union data d;
d.i = num;
insertNode(list, d);
int getback = node->data.i;

如果你有一个支持C99结构的编译器,你可以通过避免使用本地union变量来使它更整洁:

// Insert a string
insertNode(list, (union data){ .p = str});

// Insert an int
insertNode(list, (union data){ .i = num});

答案 2 :(得分:0)

你可以把它投两次:insertNode(list,(void *)(uint64_t)num);

或者你可以使用“unsigned long”代替num而不是int。至少根据我的经验,32位和64位系统上的sizeof(unsigned long)== sizeof(void *)。使用uintptr_t可能更正确;我读完标准已经有一段时间了。

答案 3 :(得分:0)

你确定你正在做你真正想做的事吗?在第一个带有字符串的示例中,您将指向字符串文字的指针传递给insertNode,而在第二个示例((void *)num)中,您将int的值转换为指向void的指针。你真的想要这样做:insertNode(list,(void *)&num);,即像第一个例子中那样传递对数据的引用吗?

另外,char *str="test";使str指向一个字符串文字,它是只读的。所以你真的应该做const char *str="test";。如果你想要一个普通(可写)字符串,那么char str[] = "test";

道歉,如果你已经知道这些事情并且实际上想在void *中存储一个int,我就无法想象为什么你会这样做。

编辑:如果您确实需要通用存储空间,那么联合将是一种安全的方法。绝对不能保证int符合标准C中的void *,即使在大多数实现中它也可能适用。