メモリ関連の操作(sizeof
またはmemset
など)にmalloc
を使用する2つのスタイルを見てきました。
sizeof(type)
、およびsizeof variable
_またはsizeof(variable)
どちらを使用しますか、または2つのスタイルを組み合わせて使用しますか。また、いつそれぞれのスタイルを使用しますか?各スタイルの長所と短所は何ですか。
例として、次の2つの状況の1つのスタイルが役立つが、他のスタイルが役に立たないことがわかります。
ポインターの間接参照が間違っている場合:
_type *var;
...
memset(var, 0, sizeof var); /* oops */
_
タイプが変わったとき:
_new_type var; /* changed from old_type to new_type */
...
memset(&var, 0, sizeof(old_type)); /* oops */
_
sizeof(variable)
よりもsizeof(type)
を優先します。考慮してください:
int a1;
float a2;
memset(&a1,0,sizeof(a1));
memset(&a2,0,sizeof(a2));
vs.
int a1;
float a2;
memset(&a1,0,sizeof(int));
memset(&a2,0,sizeof(float));
最初のケースでは、正しいサイズがmemset
に渡されていることを簡単に確認できます。 2番目のケースでは、一貫性を保つために上部と下部のセクションを絶えず確認する必要があります。
いつものように、好みはできるだけ直接あなたの意図を反映することです。
既存の変数のメモリに対して操作するつもりですか?その場合は、sizeof(variable)
を使用します。これは、気になるのは変数自体のメモリであることを可能な限り詳しく示しているためです。
たとえば、新しいインスタンスに割り当てる必要のあるメモリの量を決定するために、タイプに対して何らかの計算を行うつもりですか?その場合は、sizeof(type)
を使用してください。
つまり、私は好む
struct foo *bar;
bar = (struct foo *) malloc(sizeof(struct foo));
以上
bar = (struct foo *) malloc(sizeof(*bar));
後者の場合looksまだ存在しない変数にアクセスしようとしているようです。
一方、私は好む
char Buffer[256];
memset(Buffer, 0, sizeof(Buffer));
以上
char Buffer[256];
memset(Buffer, 0, 256 * sizeof(char));
変数の内容をゼロで埋めることが明らかに意図されているため、これは操作対象の変数です。タイプメタデータを使用しようとすると、混乱します。
私は_sizeof variable
_よりもsizeof(type)
を非常に好みます。それはあなたに型についてもっと心配してより多くの変更を加えることを強いますが、それはポインタの間接化の間違いを避けるのに役立ちます Cのバグの最も一般的な原因の中でランク付け 。
sizeof(type)
の型が変更されるバグについてはそれほど心配しません。変数のタイプを変更するときはいつでも、その変数がどこで使用されているか、およびsizeof(type)
ステートメントを変更する必要があるかどうかを確認するために、クイックスキャンを行う必要があります。常にこれを間違える可能性はありますが、ポインターの間接参照のミスよりもリスクははるかに低くなります。
_sizeof variable
_の利点の1つは配列ですが、実際には、配列をfirst/lenのペアとして渡す方がはるかに一般的であり(この場合は長さを使用するだけです)、さらに取得も非常に簡単です。この例のように、配列/ポインタの減衰によりサイズが間違っています:
_ID_INLINE mat3_t::mat3_t( float src[ 3 ][ 3 ] ) {
memcpy( mat, src, sizeof( src ) ); /* NOT the same as 3*3*sizeof(float) */
}
_
目的は冗長性を取り除くことです。変数に関連する操作にsizeofを使用する場合、明らかにそれをsizeofに反映する必要があります。はい、最初の例のように混乱する可能性がありますが、治療法はタイプではなく* varであり、目的に正しく一致しています。
このような問題を軽減するには、通常、裸のsizeofではなく、ユースケース用にトレーニングされたマクロ、テンプレート、および同様のツールを使用します。
ネイキッドmemsetの代わりに排他的に使用されるmy CLEARマクロ を参照してください。間接的なタイプミスの場合、または構造体のコンテンツがベクトルまたは文字列を取得したときに、私のお尻を数回保存しました...
ビジネスロジックは選択を定義します。
コードが特定の変数を参照し、この変数がないと、コードは意味がありません-sizeof(var)
を選択します
コードが特定のタイプの変数のセットを扱う場合は、sizeof(type)
を選択します。タイプに基づいて異なる方法で処理する多くの変数を定義するtypedef
がある場合、通常これが必要です(例:シリアル化)。これらの変数のどれが将来のコードバージョンに残るかわからない場合があるため、引数としてタイプを選択することは論理的に正しいです。そのようなtypedef
を変更しても、sizeof行には影響しません。