【问题标题】:Linked list with different types不同类型的链表
【发布时间】:2013-11-22 00:26:02
【问题描述】:

如何创建一个列表,其中每个元素都可以是不同的类型?

我现在正在做的事情是这样的:

typedef struct listitem
{
    int flavour;
    void *payload;
    struct listitem *next;
} listitem

当访问此列表中的项目时,我检查flavour 的值,然后将payload 转换为适当的类型。这种方法对我来说似乎有点大锤。

在 C99 中执行此操作的标准方法是什么?

有没有办法推断一个对象的类型,只给它的地址?

【问题讨论】:

    标签: c linked-list c99


    【解决方案1】:

    不,C 不提供反射功能,即根据地址推断对象类型的能力。你将不得不自己管理它。你做对了,但你必须自己管理味道。其他人指出了如何通过将所有替代类型放在一个联合中来减轻痛苦,这样您就不必一直强制转换。您可能会编写一些隐藏所有联合的内联函数以及不隐藏的东西。要获得一个想法:

    typedef struct listitem
    {
        int flavour;
        union {
            int i;
            char * str;
        };
        struct listitem * next;
    };
    int int_item(struct listitem * item)
    {
        if (flavour != FLAVOUR_INT)
            error("Not an integer");
        return item->i;
    }
    
    char * string_item(struct listitem * item)
    {
        if (flavour != FLAVOUR_STRING)
            error("Not a string");
        return item->str;
    }
    

    【讨论】:

    • 当我使用联合时,C 会为我创建的每个列表项的每个联合成员分配内存吗?
    • 您需要注意这一点。联合将包含用于原语(整数、长整数、双精度、字符)的空间和指向此类野兽的指针。但是,如果您需要像字符串这样大小不同的对象,则通常必须使用 malloc() 单独分配它们,然后在丢弃列表项时从列表项中释放它们。您可以向列表项添加一个函数指针,当要丢弃列表项时应该调用该函数指针。函数指针不会对原始类型执行任何操作,但会为所有需要释放的类型调用 f​​ree()。
    • 非常感谢。这整个业务(特别是添加一个用于清理的函数指针,为什么不直接称它为析构函数)听起来像是从头开始重新发明 OOP。
    • 确实;从某种意义上说,您是在重新发明 ATL 的 C++ CComVariant 类,它包装了 COM 使用的 VARIANT 结构。由于您使用 C 进行编程,因此您必须自己完成所有操作。
    【解决方案2】:

    您可以只使用 void * 的指针。您可以使用联合的其他类型:

    typedef struct listitem
    {
        int flavour; // type of data held
        union {
            int i;
            double d;
            float f;
            :
            :
        };
        struct listitem *next;
    } listitem
    

    对不起,我看错了你的问题。你自己管理味道。

    【讨论】:

    • 当我使用union 时,C 会为我创建的每个列表项的每个联合成员分配内存吗?
    • C 将为最大的联合成员分配足够的内存。工会的所有成员都在同一个位置。
    • 现在这是一个简洁的功能。我会更详细地研究它。谢谢。
    【解决方案3】:

    还有另一种方法。

    如果您的flavour 没有太多价值,您可以将其嵌入地址。与 2 的幂对齐的地址的最低有效位为 0。 In C11 you have a standard way of allocating aligned memory 然后可以用于tag your pointers

    【讨论】:

      猜你喜欢
      • 2011-01-24
      • 1970-01-01
      • 2018-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多