如何在C中处理一个数组中的不同数据类型

时间:2013-01-19 15:19:23

标签: c memory-management

我想模拟面向对象的编程,所以在C ++中,让我们考虑以下C代码:

typedef struct tAnimal{
   char * name;
   int age;
}tAnimal;

typedef struct tAnimal2{
   char * name;
   int age;
   float size;
}tAnimal2;   

在C ++中,您可以创建一个包含从同一个类继承的不同对象的表。 我想在C中做同样的事情,让我们考虑以下代码:

tAnimal ** tab;
tab = malloc(sizeof(tAnimal*)*2);
tab[0] = malloc(sizeof(tAnimal));
tab[1] = malloc(sizeof(tAnimal2));

请注意,分配有效,因为malloc返回一个void指针,而C不需要强制转换。但是我仍然无法访问size字段,因为tab元素的类型毕竟是tAnimal。

无论如何要解决这个问题吗?我想远离无效指针。

3 个答案:

答案 0 :(得分:3)

在C语言中,通常使用带有type-flag和union数据的结构:

typedef enum
{
    Animal1,
    Animal2
} AnimalType;

struct Animal
{
    AnimalType type;

    union
    {
        tAnimal  animal;
        tAnimal2 animal2;
    };
};

现在您可以创建Animal结构的数组。

答案 1 :(得分:0)

如果要访问size字段,则必须将指针强制转换为tAnimal2。注意,C ++也是如此。

您可以通过在第二个结构的开头嵌入第一个结构来模拟继承:

struct tAnimal{
   char * name;
   int age;
};

struct tAnimal2{
  struct tAnimal parent;

  float size;
};

答案 2 :(得分:0)

为了访问size中的tab[1]字段,您可以将指针强制转换为tAnimal2指针。

 tAnimal2* panimal2 = (tAnimal2*) tab[1];
 panimal2->size = 1.0;

但是,这种做法容易导致数据损坏,因为您需要一种方法来确保您投射到tAnimal2的表的元素确实是tAnimal2的实例。您可以使用其他类型字段,因为Joachim Pileborg建议检查对象的类型。