繁体   English   中英

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

[英]Cast 32 bit int to 64 void * pointer without warning

我在C中有一个“通用”链接链接,它使用void * datavoid * 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_tuintptr_t 它们是与指针大小相同的整数:

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

当然,您可以存储的最大值取决于系统,但您可以在编译时通过INTPTR_MININTPTR_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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM