étale-cohomology
étale-cohomology

Reputation: 1861

How to implement a variable-length heterogeneous sequence of structs

There's 2 structs of different sizes:

struct A{
    int x, y, z;
};

struct B{
    float x, y;
};

At runtime, the program generates a sequence of instances of these two structs.

A hand-written example could look like:

Struct A a0 = { ... };
Struct A a1 = { ... };
Struct B b0 = { ... };
Struct A a2 = { ... };
Struct B b1 = { ... };
Struct B b2 = { ... };

So, in this case, the "sequence" is a0, a1, b0, a2, b1, b2.

I'd like to "place" this sequence into some data structure. (The length of the full sequence is only known at runtime, as well as the order of appearance of each instance of struct A and struct B.)

What's the simplest way to do this?

In Python, for instance, I'd do something like:

Class A:
    def __init__(self, x, y, z):
        self.x, self.y, self.z = x, y, z

Class B:
    def __init__(self, x, y):
        self.x, self.y = x, y

# Manual example
a0 = A(...)
a1 = A(...)
b0 = B(...)
a2 = A(...)
b1 = B(...)
b2 = B(...)

my_list = []

# The list gets updated as the program runs
my_list.append(a0)
my_list.append(a1)
my_list.append(b0)
my_list.append(a2)
my_list.append(b1)
my_list.append(b2)
# etc., etc.

How can I do the equivalent in C?

Upvotes: 3

Views: 120

Answers (2)

marshal craft
marshal craft

Reputation: 447

Use of pointers makes a heterogeneous array possible.

typedef struct A {
    int x;
    int y;
    int z;
}*PA;

typedef struct B {
    float x;
    float y;
}*PB;

void main() {
    void * Instance[2];
    A a;
    B b;

    Instance[0] = &a;
    Instance[1] = &b;

    ((PA)(Instance[0]))->x = 2;
}

But now you can have any type which raises the question of just how are you supposed to know what type to expect at any given index? If you decide to just start cataloging types which are allowable then why not just use a union?

Upvotes: 1

koper89
koper89

Reputation: 655

I would suggest using union here, to wrap both structs in one:

 union Data {
      struct A A;
      struct B B;
 };

Additionally you could use enum or any other variable type to specify what you store in this union currently:

 enum DataType {
      TYPE_A = 0,
      TYPE_B
 };

And finally you wrap both of them in a struct:

 struct DataHolder {
      union Data Data;
      enum DataType DataType;
 };

Then to make it as you wanted as list you can use pointer to DataHolder or use it as array and put your list inside. Append could be using dynamic reallocation (realloc). But function to append it would need to have access to, how many items are currently inside of your list, and type of data you wish to add to your list.

Upvotes: 4

Related Questions