C:元素大小不一的数组

时间:2009-11-08 15:11:09

标签: c arrays

是否可以使用值大小不同的元素(结构)数组?

我面临的问题是我不知道如何访问元素,因为它需要强制转换。 “数组”只包含指向结构的指针。因此我决定选择无效**。由于并非每个元素都属于同一类型,因此类型也需要存储在数组中,以便在不进行粗略猜测的情况下知道要转换的内容。但这听起来效率不高。有没有更有效的方法?

5 个答案:

答案 0 :(得分:10)

不,在C中,数组的每个元素必须是相同的类型(因此也是相同的大小)。

您可能需要添加另一个抽象层,在这种情况下,您需要使用它具有的类型来注释元素,例如你可以创建一个看起来像:

的结构数组
enum ElemType {
  TypeNull,
  TypeFoo,
  TypeBar
];

struct Elem {
 enum ElemType type;
 void *realElem;
};

您必须使用插入的实际类型更新'type',并在读取数组时对其进行决策,并将指针存储到'realElem'成员中的实际元素。

struct Elem arr[42];
...
switch(arr[k].type) {
  case TypeFoo:
     handleFoo(arr[k].realElem);
     break;
  ...
}

答案 1 :(得分:6)

如果您不喜欢演员表,您可以随时使用联合(以及一个标志来指示联合应该被解释为哪种类型)

#include <stdio.h>

typedef struct {
    int a;
} A;

typedef struct B {
    double b;
} B;

typedef struct C {
    char c[20];
} C;

typedef enum {
    TypeA,
    TypeB,
    TypeC,
} type;

typedef struct {
    type type;
    union { A*a; B*b; C*c; } p;
} TypedPointer ;

void foreach (TypedPointer* list, void (*fn)(TypedPointer))
{
    while (list->p.a) {
        fn(*list);
        ++list;
    }
}

void print_member (TypedPointer ptr)
{
    switch (ptr.type) {
        case TypeA: printf("A (%d)\n", ptr.p.a->a); break;
        case TypeB: printf("B (%f)\n", ptr.p.b->b); break;
        case TypeC: printf("C (%s)\n", ptr.p.c->c); break;
    }
}

int main ()
{
    A a = { .a = 42 };
    B b = { .b = 1.01 };
    C c = { .c = "Hello World!" };

    TypedPointer ptrs[] = {
        { .type = TypeA, .p.a = &a },
        { .type = TypeB, .p.b = &b },
        { .type = TypeC, .p.c = &c }, 
        { .type = 0, .p.a = 0} };

    foreach(ptrs, print_member);

    return 0;
}

答案 2 :(得分:2)

不,C数组具有必须在编译时知道的常量大小。但是你可以通过使用指针和动态分配来解决这个问题。

这里的问题不是效率,而是类型安全。转换没有运行时性能成本,它只是与编译器通信的机制,要求它“信任你”并假设在一系列位后面有某种类型。我们谈的是安全问题,因为如果你错了,那么任何事都可以在运行时发生。

在C(静态语言)中构造不同类型的数组是不可能的。你可以做的是构造一个某个结构的数组,但是该结构保存指向不同大小的对象的指针。例如,让struct保存一个char*指针,在这种情况下,每个对象都包含一个长度或另一个长度的字符串,因此具有可变大小(就运行时使用的总内存而言,不是就连续空间而言)使用)。

如果您希望每个对象的行为与其他对象不同,那么您可以通过使用函数指针数组来模拟多态,然后添加一个指向任何函数的结构的函数指针必要时。

答案 3 :(得分:0)

为此,我们使用指向实际对象的指针数组。

指针的大小都相同。

他们指向的对象可以是不同的大小。

“歧视联盟”对此很有效。

typedef struct { ... } this_type;
typedef struct { ... } that_type;
typedef struct { 
     int subtype;
     union {
         this_type this;
         that_type that
     }
} discriminated_union;

指向discriminated_union的数组指针运行良好。

答案 4 :(得分:0)

Casts效率不高,因为它们只是告诉计算机如何解释内存区域。当它们被编译为汇编时,编译器将创建根据需要解释内存区域的程序集。