我正在尝试创建一个可以保存通用值的结构。下面的代码可以工作,但我收到一个关于从指针到整数的转换的编译器警告。这是在64位系统上。
struct node
{
void *key;
void *value;
};
void insert(struct node *ht, void *key, void *value)
{
ht->key = key;
ht->value = value;
return;
}
int main()
{
struct node *t = (struct node *)malloc(sizeof(struct node));
insert(t, (void *)3, (void *)5);
printf("[%d]->[%d]\n", (int)t->key,(int)t->value);
free(t);
return 0;
}
我甚至不确定这是否是正确的方法。我有点黑了。如果有正确的方法,请告诉我。
答案 0 :(得分:8)
编译器会在从void *
转换为int
时尝试警告您丢失了比特。它不知道void *
实际上是int
强制转换,所以丢失的位没有意义。
双重演员会解决这个问题(int)(uintptr_t)t->key
它首先将void *
投射到uintptr_t
(相同尺寸,无警告),然后uintptr_t
投放到int
(数字到数字,无警告)。
您需要包含<stdint.h>
以获得uintptr_t
类型(与指针大小相同的整数类型)。
答案 1 :(得分:3)
有一点值得记住的是,在64位系统中,指针是64位值[内存地址。]
int只是一个32位值,无论您使用的是什么体系结构。无论何时尝试将64位值分配给32位值而不显式强制转换,编译器都会发出警告[已授予,它仍可以正常工作,但通常不是很好的做法。]
如果你不反对使用无符号整数,可能更容易使用uint_64t或类似的东西,这将避免64位到32位的赋值(uint_64t是无符号的64位int)
希望有所帮助。
你可以做的一件事是:
int key = 3;
int value = 5;
insert(t, (void *) &key, (void *) &value);
printf("[%d]->[%d]\n", (int) *(t->key), (int) *(t->value));
然而,在做这样的事情时要非常小心。除非你可以保证设置指针并且它的值/类型不变,否则绝对不知道该指针存储的值是什么是不可能的。除非您添加枚举字段或存储指针位置存储的值类型的东西 - 但这种方法会失败。
答案 2 :(得分:2)
您发布的代码存在很多问题。
首先:
printf("[%d]->[%d]\n", (int)t->key,(int)t->value);
打印指针时,打印指针。使用%p。见这里:
http://www.cplusplus.com/reference/cstdio/printf/
第二
insert(t, (void *)3, (void *)5);
我不确定您预期会发生什么,但您存储的地址不是VALUE。 (即您将密钥设置为指向地址3内容的指针,并将值设置为指向地址5内容的指针。)
第三
struct node *t = (struct node *)malloc(sizeof(struct node));
此处您已分配节点,但尚未分配任何内容以保存内容。您的节点只保留一些指针(ADDRESSES),它不包含任何VALUES。我不确定这是不是你想要的。
最后,您的编译器正确地警告您。你有可能失去精确度。就像@JonathanLeffler所说,使用uintptr_t。