0

memset に関する別の質問があります。編集しているコードに問題があるように見えます (または、別のファイルで同じように行われていません)。

A::LRM las[9]; //A and LRM are both structures with BOOLS and INTS
memset(&las, 0, sizeof(las));

typedef Sec SecArray[16];
SecArray rad_array;
memset(rad_array, 0, sizeof(SecArray));

rad_array2 番目の例は、 が配列の最初の位置と同じであるため、正しいように見えます。それならsizeof(SecArray))理にかなっています。最初のものは私には正しくないようです。すべての構造体は単なる BOOL であり、INTS は動的なものではありません。

memset に関する私の他の投稿からの私の理解は、それがこの形式に従っているということでした。

memset("pointer to object", "what to set it to", "size of object")

私の理論が間違っているとしたら、ここで何が起こっているのか正確に教えてもらえますか?

4

5 に答える 5

11

どちらの呼び出しmemsetも正しいです。との両方sizeof(las)(または のみsizeof las)sizeof(SecArray)は、配列全体のサイズを返します。

最初の引数が心配な場合は、両方とも機能します。配列全体へのポインター ( &las) または最初の要素へのポインター (rad_arrayこのコンテキストでは) は、 と同様にうまく機能しmemsetます。

一般に、使用法に関してsizeofは、タイプに依存しないため、最初のアプローチを使用することをお勧めします。適切なプログラミング方法は、ステートメントで型名を言及しないことです。つまり、型名をできるだけ宣言に限定してください。

最初の引数については、配列の場合は好みの問題ですが、一般的には、型のオブジェクトがある場合はT

T t;

を使用してゼロで埋めたい場合memset、通常は次のように行います

memset(&t, 0, sizeof t);

配列がその規則の例外であるべき理由がわかりません (特に、型の正確な性質が typedef 名の背後に隠されている場合)。上記は、配列型、構造体型、またはその他の型にmemset(&t, ...関係なく機能します。が配列型であるという理由だけでT、なぜ突然削除する必要があるのか​​ わかりません。まったく逆に、コードを可能な限り型に依存しないようにするために、それを維持します。&T&

最後に、C++ ではどちらの場合も、memsetまったく使用せずに実行することをお勧めします。

A::LRM las[9] = {};
SecArray rad_array = {};

代わりは。

于 2010-05-07T15:38:06.117 に答える
1

設定するメモリの全長を指定する必要があります。
memset は、引数について何も知らない C 関数です。引数の実際の意味は

memset("pointer to memory", "what to set each byte to", "number of bytes to set")

したがって、これは実際には優れています:

A::LRM las[9]; //A and LRM are both structures with BOOLS and INTS
memset(&las, 0, sizeof(A::LRM)*9);

typedef Sec SecArray[16];
SecArray rad_array;
memset(rad_array, 0, sizeof(Sec)*16);

あなたが提供した両方の例は実際には機能しますが、配列がポインターに減衰するのは簡単であるため、壊れやすいです。その後、期待どおりに機能しません(たとえば、配列を memset を実行する関数、または new を使用してダイナミック アロケーションに切り替えます)。

于 2010-05-07T15:40:48.693 に答える
0

memset の最後の引数は、オブジェクトのサイズではなく、「オブジェクトへのポインター」が指すオブジェクトの「配列」のサイズです。

あなたが持っているとしましょう:

memset(ptr, value, length);

memset は と の間のすべてのバイトを に設定ptrptr+sizeof(*ptr)*length-1ますvalue

于 2010-05-07T15:38:02.757 に答える
0

最初の例は機能しますが、次のことをお勧めします。

A::LRM las[9]; 
memset(las, 0, sizeof(las)); // <== no ampersand needed

データ型が何でAあるかは問題ではないことに注意してください。A::LRM

しかし

構造体をそのように初期化するべきではありません。今日は BOOL と int に過ぎませんが、明日何でもあり得るからです。誰かが にクラスを追加した場合A::LRMmemset()はそのプライベート データを上書きしますが、手遅れになるまでわかりません。

于 2010-05-07T15:54:54.283 に答える
0

memsetメモリをゼロバイトで埋めます。一般に、メンバーをゼロに初期化することと同じではありません。標準の ISO C++ (または C) に固執している限り、唯一の保証は、all-bits-0 が有効であるか、charまたはunsigned charに等しい値であることです0。整数型の場合でも、値ビットの外側にパディングが許可されているため、これは必ずしも真である必要はありません。これらのビットのすべてゼロはトラップ表現になる可能性があります。

floatまたはへのポインタ、またはdouble0.0のポインタを初期化するのは間違いなく適切な方法ではありませんnull。これらの型のすべてのビットがゼロではない既存の準拠実装があり0ます。

とにかく、空の集約初期化子を使用することで、コードをより短く、完全に移植可能な方法で書くことができます。

A::LRM las[9] = {};

これにより、配列が値で初期化されます。これにより、すべての要素がゼロで初期化されます。POD 構造体の場合は、すべてのフィールドがゼロで初期化されます。

もちろん、これはそれA::LRMが POD 構造体であることを前提としています。そうでない場合は、memset物事を壊す可能性がさらに高くなります。実際には、そのコンストラクターを使用し、コンストラクターが初期化しなかったフィールドに割り当てる必要があります。

于 2010-05-07T18:59:53.493 に答える