1

私がそのような構造体を持っているとしましょう:

typedef struct {
    char *str;
    int len;
} INS;

そして、その構造体の配列。

INS *ins[N] = { &item, &item, ... }

ポインタとしてではなく、構造体自体としてその要素にアクセスしようとすると、すべてのフィールドが一時的なローカルの場所にコピーされますか?

for (int i = 0; i < N; i++) {
    INS in = *ins[i];
    // internaly the above line would be like:
    // in.str = ins[i]->str;
    // in.len = ins[i]->len;
}

では、構造体フィールドを増やすと、よりコストのかかる代入操作になりますか?

4

4 に答える 4

2

正しい、inコピーです*ins[i]

メモリ消費を気にする必要はありませんが、コードはおそらく正しくないでしょう。オブジェクトinはループ本体の最後で終了し、加えた変更inは永続的な効果がありません!

于 2012-08-14T15:02:57.767 に答える
1

コンパイラ構造体のコピーを最適化し、代わりに配列からメンバーに直接アクセスして、コピーを使用する C コードで必要な値を提供するか、使用する個々のメンバーだけをコピーする場合があります。優れたコンパイラはこれを行います。

ポインターを介して値を格納すると、この最適化が妨げられる可能性があります。たとえば、ルーチンに int へのポインターも含まれているとしますp。コンパイラがコードINS in = *ins[i]を処理するとき、次のように「考える」ことができますins[i]。代わりに、それがコピーであることを覚えておき、in後で使用するときにメンバーを取得します。」ただし、コードに が含まれている場合、コンパイラが を指していないと推測できない限り*p = 3、これは変更される可能性があります。(キーワードを使用して、コンパイラがその推論を行うのを助ける方法があります。)ins[i]pins[i]restrict

要約すると、一見高価に見える操作は、優れたコンパイラによって効率的に実装される可能性があります。安価に見える操作は高価な場合があります (書き込み*pは大きな最適化を破ります)。一般に、アルゴリズムを明確に表現するコードを記述し、コンパイラに最適化させる必要があります。

コンパイラがこれを最適化する方法を拡張します。次のように書くとします。

for (int i = 0; i < N; i++) {
    INS in = *ins[i];
    ...
}

ここで、「...」内のコードは in.str と in.len にアクセスしますが、INS 構造体に追加する他の 237 のメンバーにはアクセスしません。その後、コンパイラは自由にこのコードを次のように変換できます。

for (int i = 0; i < N; i++) {
    char *str = *ins[i].str; 
    int len = *ins[i].len;
    ...
}

つまり、見かけ上は INS 構造体のすべてをコピーするステートメントを書いたとしても、コンパイラは実際に必要な部分だけをコピーする必要があります。(実際には、それらの部分をコピーする必要さえありません。ソースコードを直接たどった場合と同じ結果が得られるプログラムを作成するだけで済みます。)

于 2012-08-14T15:52:52.767 に答える
1

構造体の代入はmemcpy. はい、構造が大きいほど費用がかかります。逆説的に、構造が大きくなればなるほど、別のフィールドを追加するための追加費用を測定することが難しくなります。

于 2012-08-14T15:05:58.127 に答える
1

はい、value semanticsC には構造体があります。したがって、構造体を別の構造体に割り当てると、メンバーごとのコピーが作成されます。ポインターは引き続き同じオブジェクトを指すことに注意してください。

于 2012-08-14T15:06:32.817 に答える