次のように、構造体のインスタンスを別のインスタンスに割り当てることができますか?
struct Test t1;
struct Test t2;
t2 = t1;
単純な構造で機能するのを見てきましたが、複雑な構造でも機能しますか?
タイプに応じてデータ項目をコピーする方法、つまりint
と文字列を区別する方法をコンパイラーはどのように知っていますか?
構造が同じタイプの場合ははい。メモリコピーと考えてください。
はい、構造体の割り当てがサポートされています。ただし、問題があります。
struct S {
char * p;
};
struct S s1, s2;
s1.p = malloc(100);
s2 = s1;
これで、両方の構造体のポインターがメモリの同じブロックをポイントします-コンパイラーは、ポイントされたデータをコピーしません。現在、どの構造体インスタンスがデータを所有しているかを知ることは困難です。これが、C++がユーザー定義可能な代入演算子の概念を発明した理由です。このケースを処理する特定のコードを書くことができます。
この例をまず見てください:
単純なCプログラムのCコードを以下に示します
struct Foo {
char a;
int b;
double c;
} foo1,foo2;
void foo_assign(void)
{
foo1 = foo2;
}
int main(/*char *argv[],int argc*/)
{
foo_assign();
return 0;
}
foo_assign()の同等のASMコードは
00401050 <_foo_assign>:
401050: 55 Push %ebp
401051: 89 e5 mov %esp,%ebp
401053: a1 20 20 40 00 mov 0x402020,%eax
401058: a3 30 20 40 00 mov %eax,0x402030
40105d: a1 24 20 40 00 mov 0x402024,%eax
401062: a3 34 20 40 00 mov %eax,0x402034
401067: a1 28 20 40 00 mov 0x402028,%eax
40106c: a3 38 20 40 00 mov %eax,0x402038
401071: a1 2c 20 40 00 mov 0x40202c,%eax
401076: a3 3c 20 40 00 mov %eax,0x40203c
40107b: 5d pop %ebp
40107c: c3 ret
Assemblyで割り当てが単に「mov」命令に置き換えられることがわかるように、割り当て演算子は単に、あるメモリ位置から別のメモリ位置にデータを移動することを意味します。割り当ては、構造体の直接のメンバーに対してのみ行われ、構造体にComplexデータ型がある場合、コピーに失敗します。ここでCOMPLEXは、リストを指すポインターの配列を保持できないことを意味します。
構造内の文字の配列自体は、ほとんどのコンパイラでは機能しません。これは、割り当てがデータ型を複雑な型と見なすことなくコピーを試みるだけだからです。
これは、memcpy()
で行うのと同じように、単純なコピーです(実際、一部のコンパイラは、そのコードに対してmemcpy()
の呼び出しを実際に生成します)。 Cには「文字列」はなく、文字列へのポインタのみがあります。ソース構造にそのようなポインターが含まれる場合、chars自体ではなく、ポインターがコピーされます。
実数部と虚数部を持つ複素数のような「複雑な」という意味ですか?これはありそうにないので、「複雑」とはC言語の観点から具体的なものを意味しないので、例を挙げる必要があります。
構造の直接メモリコピーを取得します。それがあなたが望むものであるかどうかは、構造に依存します。たとえば、構造にポインターが含まれる場合、両方のコピーは同じデータを指します。これはあなたが望むものかもしれませんし、そうでないかもしれません。それはあなたのプログラムの設計次第です。
「スマート」コピー(または「ディープ」コピー)を実行するには、コピーを実行する関数を実装する必要があります。構造自体にポインターと、ポインターも含む構造が含まれている場合、およびおそらくそのような構造へのポインターが含まれている場合(おそらく「複雑」という意味です)、これを実現するのは非常に難しく、保守が困難です。簡単な解決策は、C++を使用して、各構造体またはクラスのコピーコンストラクターと代入演算子を実装することです。その後、それぞれが独自のコピーセマンティクスを担当し、代入構文を使用できます。