[英]Cast 32 bit int to 64 void * pointer without warning
I have a "generic" linked link in C that takes void * data
to store the data in a Node. 我在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;
This is because int
is 32 bit, but void *
is 64 bit on x64 machine. 这是因为
int
是32位,但x64机器上的void *
是64位。 What is the best practice to get rid of this error? 摆脱这个错误的最佳做法是什么?
Use intptr_t
or uintptr_t
. 使用
intptr_t
或uintptr_t
。 They are integers of the same size as a pointer: 它们是与指针大小相同的整数:
#include <stdint.h>
...
intptr_t num = 1;
insertNode(list, (void *) num);
intptr_t getback = (intptr_t) node->data;
Of course, the maximum value that you can store depends on the system, but you can examine it at compile time via INTPTR_MIN
and INTPTR_MAX
. 当然,您可以存储的最大值取决于系统,但您可以在编译时通过
INTPTR_MIN
和INTPTR_MAX
检查它。
Using a void *
member to store an integer value isn't very good practice - apart from anything else, there's no guarantee what range of integers are storable in this way. 使用
void *
成员存储整数值不是很好的做法 - 除了其他任何东西,不能保证以这种方式存储的整数范围。 If you want to store either a pointer or an integer in your structure, then what you should be using is a union
: 如果要在结构中存储指针或整数,那么您应该使用的是
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;
If you have a compiler that supports C99 constructs, you can make it a little neater by avoiding the local union
variable: 如果你有一个支持C99结构的编译器,你可以通过避免使用本地
union
变量来使它更整洁:
// Insert a string
insertNode(list, (union data){ .p = str});
// Insert an int
insertNode(list, (union data){ .i = num});
You can cast it twice: insertNode( list, (void *)(uint64_t) num); 你可以把它投两次:insertNode(list,(void *)(uint64_t)num);
Or you can use "unsigned long" for num instead of int. 或者你可以使用“unsigned long”代替num而不是int。 At least in my experience, sizeof(unsigned long) == sizeof(void *) on both 32 and 64-bit systems.
至少根据我的经验,32位和64位系统上的sizeof(unsigned long)== sizeof(void *)。 Using uintptr_t may be more correct;
使用uintptr_t可能更正确; it's been a while since I've read the standards.
自从我阅读标准以来已经有一段时间了。
Are you sure you're doing what you actually want to be doing? 你确定你正在做你真正想做的事吗? In the first example with the string you are passing the pointer to the string literal to insertNode, while in the second example (
(void *)num
) you are casting the value of the int to a pointer to void. 在第一个带有字符串的示例中,您将指向字符串文字的指针传递给insertNode,而在第二个示例中(
(void *)num
),您将int的值转换为指向void的指针。 Did you actually want to do this: insertNode(list,(void *)&num);
你真的想要这样做:
insertNode(list,(void *)&num);
, ie, passing the reference to the data like you were doing in the first example? ,即像第一个例子中那样将引用传递给数据?
Also as an aside, char *str="test";
另外,
char *str="test";
makes str point to a string literal, which is read-only. 使str指向一个字符串文字,它是只读的。 So you really should be doing
const char *str="test";
所以你真的应该做
const char *str="test";
. 。 If you wanted a normal (writable) string then
char str[] = "test";
如果你想要一个普通(可写)字符串,那么
char str[] = "test";
. 。
Apologies if you already knew these things and actually wanted to store an int in a void *
, I just can't imagine why you would. 抱歉,如果你已经知道这些事情并且实际上想要将int存储在
void *
,我无法想象为什么你会这样做。
Edit: If you actually want generic storage space then a union would be a safe approach. 编辑:如果你真的想要通用存储空间,那么联合将是一种安全的方法。 There is absolutely no guarantee that an int will fit in a
void *
in standard C, even though in most implementations it probably does. 绝对不能保证int在标准C中适合
void *
,即使在大多数实现中它也可能。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.