4

したがって、基本的に、最初の構造体のすべてのメンバーと2番目の構造体のすべてのメンバーを追加したいと思います。構造体は同じタイプです。このような:

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;
}

ただし、構造体が大きくなり続けると、この方法は奇妙になります。より少ないコード行でそれを行う方法はありますか?そして、できれば高度なポインタマジックなしで?

4

4 に答える 4

4

代わりに配列と for ループを使用して数値を追加します。

struct Foo
{
    int bars[100];
};

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

mallocコンパイル時に配列サイズが不明な場合は、構造体をこれに変更してから、3 つの変数すべてに対して malloc を実行Fooできます。

struct Foo
    {
        int *bars;
    };
于 2012-11-22T18:32:25.983 に答える
3

名前付きフィールド ( bar1.. barN) の快適さと、操作を自動化するためにループできる配列のようなものが必要です。まず、構造体 (メモリ内のフィールドの密な表現) を定義します。

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

次に、その構造体で使用されるフィールドの数を知る必要があります。

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

(C++ では、いくつかのテンプレート マジック foo を使用できます。ここでは、単純なバリアントとしてプリプロセッサを使用します)。次に、 をstruct VectorFieldsの配列と組み合わせてint、サイズが一致するようにしunionます。

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

(注:VECTOR_FIELD_LENコンパイラにとって既知の定数値である必要があるため、プリプロセッサは以前のものでした。) これで、名前 ( .fields.a) またはインデックス ( .raw[0]) のいずれかでデータにアクセスできるようになりました。それでは、 を足し合わせる関数を書きましょうVector:

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];
    }
}

次のように使用できます。

#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;
}
于 2012-11-22T19:09:29.153 に答える
3

「高度なポインター マジック」と呼ぶものに応じて、次の適度に魔法のコードを使用できます。

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;
}

の定義を変更するときFooは、最初と最後のフィールドの名前を更新するだけです。これは、すべてのフィールドが同じタイプの場合にのみ機能します。

于 2012-11-22T18:46:18.907 に答える
1

sしかない場合はint、配列を使用できます

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;
}
于 2012-11-22T18:34:51.233 に答える