[英]Cast 32 bit int to 64 void * pointer without warning
我在C中有一个“通用”链接链接,它使用void * data
将void * data
存储在Node中。
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位。 摆脱这个错误的最佳做法是什么?
使用intptr_t
或uintptr_t
。 它们是与指针大小相同的整数:
#include <stdint.h>
...
intptr_t num = 1;
insertNode(list, (void *) num);
intptr_t getback = (intptr_t) node->data;
当然,您可以存储的最大值取决于系统,但您可以在编译时通过INTPTR_MIN
和INTPTR_MAX
检查它。
使用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});
你可以把它投两次:insertNode(list,(void *)(uint64_t)num);
或者你可以使用“unsigned long”代替num而不是int。 至少根据我的经验,32位和64位系统上的sizeof(unsigned long)== sizeof(void *)。 使用uintptr_t可能更正确; 自从我阅读标准以来已经有一段时间了。
你确定你正在做你真正想做的事吗? 在第一个带有字符串的示例中,您将指向字符串文字的指针传递给insertNode,而在第二个示例中( (void *)num
),您将int的值转换为指向void的指针。 你真的想要这样做: insertNode(list,(void *)&num);
,即像第一个例子中那样将引用传递给数据?
另外, char *str="test";
使str指向一个字符串文字,它是只读的。 所以你真的应该做const char *str="test";
。 如果你想要一个普通(可写)字符串,那么char str[] = "test";
。
抱歉,如果你已经知道这些事情并且实际上想要将int存储在void *
,我无法想象为什么你会这样做。
编辑:如果你真的想要通用存储空间,那么联合将是一种安全的方法。 绝对不能保证int在标准C中适合void *
,即使在大多数实现中它也可能。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.