pampeho
pampeho

Reputation: 704

Adding (or doing any other math) every member of two same structs with less code

So, basically, I want to addify every member of first struct, with every member of second struct, and the structs are of same type. Like this:

struct Foo
{
    int bar1;
    int bar2;
    int bar3;
    int bar4;
    int bar5;
}

Foo AddFoos(Foo foo1, Foo foo2)
{
    Foo foo3;
    foo3.bar1 = foo1.bar1 + foo2.bar1;
    foo3.bar2 = foo1.bar2 + foo2.bar2;
    foo3.bar3 = foo1.bar3 + foo2.bar3;
    foo3.bar4 = foo1.bar4 + foo2.bar4;
    foo3.bar5 = foo1.bar5 + foo2.bar5;
    return foo3;
}

However, when structs keep getting bigger, this way is weird. Is there any way to do it with less lines of code? And preferably without advanced pointer magic?

Upvotes: 4

Views: 10706

Answers (4)

akira
akira

Reputation: 6147

You want the comfort of named fields (bar1 .. barN) and something like an array you can loop over to automate the operations. First we define the struct (a dense representation of the fields in memory):

struct VectorFields {
    int a;
    int b;
    int c;
};

Then we need to get to know the number of the fields used in that struct:

#define VECTOR_FIELDS_LEN (sizeof(struct VectorFields) / sizeof(int))

(In C++ you could use some template magic foo, here we just use the preprocessor as a simpler variant). Next, we combine the struct VectorFields with an array of int so both match in size, also known as union:

union Vector {
    struct VectorFields fields;
    int raw[VECTOR_FIELD_LEN];
};

(Note: VECTOR_FIELD_LEN must be a known constant value to the compiler, hence the preprocessor thingy before.) You are now able to access the data either by it's name (.fields.a) or by an index (.raw[0]). So, let's write the function which adds the Vector together:

void vector_add(union Vector* result, union Vector* a, union Vector* b) {
    int i;
    for (i = 0; i < TUPLE_LEN; i++) {
        result->raw[i] = a->raw[i] + b->raw[i];
    }
}

You might use it like this then:

#include <stdio.h>
int main() {
    union Vector a = { .fields = { 1, 2, 3 } };
    union Vector b = { .fields = { 4, 5, 6 } };
    union Vector sum;

    vector_add(&sum, &a, &b);

    printf("%d %d %d\n", sum.fields.a, sum.fields.b, sum.fields.c);
    return 0;
}

Upvotes: 3

Olaf Dietsche
Olaf Dietsche

Reputation: 74078

If you have only ints you can use an array

struct Foo {
    int bar[5];
};

Foo AddFoos(Foo f1, Foo f2)
{
    Foo f3;
    int i;
    for (i = 0; i < 5; ++i)
        f3.bar[i] = f1.bar[i] + f2.bar[i];

    return f3;
}

Upvotes: 1

anatolyg
anatolyg

Reputation: 28278

Depending on what you call "advanced pointer magic", you can use the following moderately magical code:

Foo AddFoos(Foo foo1, Foo foo2)
{
    Foo foo3;
    int *pointer1 = &foo1.bar1; // first field here
    int *pointer2 = &foo2.bar1; // first field here
    int *pointer3 = &foo3.bar1; // first field here
    while (pointer3 <= &foo3.bar5) // last field here
    {
        *pointer3++ = *pointer1++ + *pointer2++;
    }
    return foo3;
}

When you change the definition of Foo, just update the names of the first and last field. This will only work when all fields are of the same type.

Upvotes: 3

P.P
P.P

Reputation: 121407

Use an array instead and a for loop to add the numbers:

struct Foo
{
    int bars[100];
};

for (i=0;i<100;i++)
{
foo3.bars[i]=foo1.bars[i]+foo2.bars[i];
}

You can malloc if the array size is unknown at compile time and change the struct to this and then malloc for all three Foo variables.

struct Foo
    {
        int *bars;
    };

Upvotes: 4

Related Questions