6

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

我什至不确定这是否是正确的方法。我有点破解它。请让我知道是否有适当的方法来做到这一点。

4

3 回答 3

9

编译器会尝试警告您在从void *to转换时丢失位int。它不知道这void *实际上是一个int演员表,所以丢失的位是没有意义的。

双重演员可以解决这个问题(int)(uintptr_t)t->key
它首先转换void *uintptr_t(相同大小,无警告),然后uintptr_t转换为int(数字到数字,无警告)。
您需要包含<stdint.h>类型uintptr_t(与指针大小相同的整数类型)。

于 2013-02-05T15:54:53.770 回答
3

需要记住的一件事是,在 64 位系统中,指针是 64 位值 [内存地址]。

int 只是一个 32 位的值,无论您使用什么架构。每当您尝试将 64 位值分配给 32 位值而不显式转换它时,编译器都会抛出警告 [授予,它仍然可以工作,但通常不是好的做法。]

如果您不反对使用无符号整数,则使用 uint_64t 或类似的东西可能会更容易,这将避免 64 位到 32 位的赋值(uint_64t 是无符号的 64 位整数)

希望有帮助。

你可以做的一件事是:

int key = 3;
int value = 5;
insert(t, (void *) &key, (void *) &value);
printf("[%d]->[%d]\n", (int) *(t->key), (int) *(t->value));

但是,在做这样的事情时要非常小心。除非您可以保证设置了指针并且它的值/类型不变,否则不可能绝对知道该指针存储的值是什么。除非您添加一个枚举字段或存储存储在指针位置的值类型的东西——但这违背了目的。

于 2013-02-05T16:57:33.823 回答
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);

我不确定您期望发生什么,但您存储的是地址而不是值。(即,您将键设置为指向地址 3 内容的指针,并将值设置为指向地址 5 内容的指针)。

第三:

struct node *t = (struct node *)malloc(sizeof(struct node));

在这里,您已经分配了节点,但还没有分配任何东西来保存内容。您的节点仅包含一些指针(地址),它不包含任何值。我不确定这是否是你想要的。

最后,您的编译器正确地警告您。您有可能会失去精确度。就像@JonathanLeffler 所说,使用 uintptr_t。

于 2013-02-05T16:50:10.757 回答