Cで文字列を割り当てる際に正しい形式はどれですか?
char *sample;
sample = malloc ( length * sizeof(char) );
また
sample = malloc ( length * sizeof(char*) );
1バイトかかるchar*
のに4バイトかかるのはなぜですか?char
Cで文字列を割り当てる際に正しい形式はどれですか?
char *sample;
sample = malloc ( length * sizeof(char) );
また
sample = malloc ( length * sizeof(char*) );
1バイトかかるchar*
のに4バイトかかるのはなぜですか?char
目標が文字列を格納することであると仮定するとlength
、正しい割り当ては次のようになります。
sample = malloc(length + 1);
ノート:
sizeof (char)
。常に 1 であり、値を追加しません。length
は、文字列の表示可能な文字の長さであると想定しました。つまり、 の戻り値はstrlen()
になりますlength
。malloc()
もすべきではないことを指摘する価値があります。大きい理由char *
は、ポインター型であり、ポインターはほとんどの場合、1 文字よりも大きいためです。多くのシステム (あなたのシステムなど) では、それらは 32 ビットですが、文字はわずか 8 ビットです。ポインタはマシンのメモリ内の任意のアドレスを表すことができる必要があるため、より大きなサイズが必要です。64 ビット コンピュータでは、ポインタは多くの場合 64 ビット、つまり 8 文字です。
char が 1 バイトかかるのに、char* が 4 バイトかかるのはなぜですか?
32 ビット システムを使用しているため、ポインターは 4 バイト必要です。char*
ポインタです。
char
常に正確に 1 バイトを使用するため、次のように掛ける必要はありませんsizeof(char)
。
sample = malloc (length);
length
null 終了のためにすでにパディングされていると想定しています。
sample = malloc(length);
正しいものです
char*
はポインタであり、ポインタは4バイトを使用します(たとえば、32ビットプラットフォームの場合)
char
はcharであり、charは1バイトを使用します
sample = malloc ( length * sizeof(char) );
length
文字数にメモリを割り当てたい場合は、最初が正しいものです。
char*
プラットフォームではたまたま 4 バイトのポインタ型です。したがって、sizeof(char*)
4 が返されます。
ただしsizeof(char)
、常に 1 であり、smae は C 標準で保証されています。
あなたの場合、長さ文字の配列を割り当てたいとします。指しているサイズのsample
倍数の配列へのポインターに格納します。length
はsizeof(char*)
へのポインタのサイズですchar
。のサイズではありませんchar
。
良い習慣は
sample = malloc(length * sizeof(*sample));
それを使用して、ポイントしたいもののサイズの長さを予約します。これにより、サンプルを別の種類のデータとして宣言するだけで、いつでもデータ型を変更できます。
int *sample;
sample = malloc(length * sizeof(*sample)); // length * 4
char *sample;
sample = malloc(length * sizeof(*sample)); // length * 1
既にnullength
ターミネータのアカウントがある場合、次のいずれかを記述します。
sample = malloc(length);
また:
sample = malloc(length * sizeof(*sample));
sizeof(char*)
はポインターのサイズであり、割り当てられたバッファーに必要なサイズとはまったく関係ありません。だから絶対に使わないでください。
私の最初のスニペットは、文字列操作コードには十分な IMO です。C プログラマーは、C のメモリと文字列の長さがどちらも の倍数で測定されることを知っていますsizeof(char)
。誰もが常に知っている変換係数をそこに入れる必要はありません1
。
私の 2 番目のスニペットは、一般的に割り当てを記述する唯一の正しい方法です。したがって、すべての割り当てに一貫性を持たせたい場合は、文字列の割り当てでもそれを使用する必要があります。すべての割り当てが一貫しているように見える理由として、次の 2 つが考えられます (どちらも IMO はかなり弱いですが、実際には間違っているわけではありません)。
length
使用すると、バイト単位ではなくワイド文字単位で測定されたときに適切な割り当てを取得することが思い出されます。一貫した形式として使用するということは、が測定される単位と同時にsizeof(*sample)
の型を更新すると仮定すると、そのコード行をまったく変更する必要がないことを意味します。sample
length
その他のオプションは次のとおりです。
sample = calloc(length, 1);
sample = calloc(length, sizeof(char));
sample = calloc(length, sizeof(*sample));
ここではおそらくかなり無意味ですが、メモリをゼロにすることの些細な二次的効果と同様に、使用する予定のオブジェクトの数とサイズを明示的に分離するのに対し、合計サイズが必要なだけでcalloc
あるという興味深い違いがあります。 .malloc
malloc
特定のケースでは、次の 2 つの異なることを行っています。
最初のケースでは:sample = malloc ( length * sizeof(char) );
1バイトlength
のタイプのサイズを掛けて割り当ててchar
います
2番目のケースでは: sample = malloc ( length * sizeof(char*) );
マシン上で4バイトlength
のポインタのサイズを掛けて割り当ててい
ます。char
ケース 1 は不変のままですが、2 番目のケースではサイズが可変であると考えてください。
どのタイプの場合でもT
、通常の形式は
T *p = malloc(N * sizeof *p);
また
T *p;
...
p = malloc(N * sizeof *p);
ここで、は割り当てたいN
タイプの要素の数です。T
式の*p
タイプT
は、であるため、sizeof *p
と同等sizeof (T)
です。
sizeof
これは、またはのような演算子であり、ライブラリ関数ではないことに注意してください。括弧は、オペランドがまたはのような型名である場合にのみ必要です。 &
*
int
char *