简体   繁体   English

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

[英]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 * 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;

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_tuintptr_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_MININTPTR_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.

相关问题 如何使用C在64位平台中将void *转换为int? - How to cast a void* to int in 64-bit platforms, using C? 如何将64位void指针转换为32位void指针? - How to convert 64bit void pointer into 32bit void pointer? GCC 警告:从 &#39;int&#39; 初始化 &#39;int32_t *&#39; {aka &#39;int *&#39;} 使指针来自整数而不进行强制转换 [-Wint-conversion] - GCC warning: initialization of 'int32_t *' {aka 'int *'} from 'int' makes pointer from integer without a cast [-Wint-conversion] 从'void *'赋值给'int'使得integer从指针没有强制转换 - assignment to 'int' from 'void *' makes integer from pointer without a cast 如何将 void 指针转换为 int? - How to cast a void pointer to an int? 预先警告:“算术溢出:转换32位值,然后转换为64位值。” - Prefast Warning:“Arithmetic Overflow: 32-bit value is shifted, then cast to 64-bit value.” 转换为uint64时,int32或32bit指针的意外符号扩展 - Unexpected sign extension of int32 or 32bit pointer when converted to uint64 64位函数返回32位指针 - 64 bit function returns 32 bit pointer 在取消引用 void 指针后强制转换为 int 是否正确? - It is correct to cast to int after dereferencing a void pointer? C:在处理 32 位程序时,在 Windows 64 位计算机上将 int 转换为 int* 时出现警告 - C: Warning when casting int to int* on Windows 64-bit machine when working on 32-bit program
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM