编译器警告 - 从指针转换为不同大小的整数

时间:2013-02-05 15:49:36

标签: c generics

我正在尝试创建一个可以保存通用值的结构。下面的代码可以工作,但我收到一个关于从指针到整数的转换的编译器警告。这是在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;
}

我甚至不确定这是否是正确的方法。我有点黑了。如果有正确的方法,请告诉我。

3 个答案:

答案 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。