「みんな教えて! 選手権!!」開催のお知らせ

char *p = new char[SIZE];
上記の方法で動的メモリを確保した場合
確保したメモリの初期化は、
memset(p, 0x00, SIZE);
のほかに方法はありますでしょうか?
個人的にSIZEを指定してしまうのがキレイではないような気がしています。

memset(p, 0x00, sizeof(p));
では、sizeof(p)はchar* のサイズなので正しく初期化できず、

for (int i = 0; i < SIZE; i++){
memset(p[i], 0x00, sizeof(p[i]));
}
では、コンパイルエラーが出てしまいます。
(new char[SIZE]で確保した場合には、p[i]のように配列としてアクセスできないのでしょうか?
単にchar p[SIZE]の場合には、当然配列としてアクセスできるのに。。。)

一般的な初期化方法のほかにも何かコメントでも良いので経験あるかたいらっしゃいましたら教えてください。
宜しくお願いいたします。

A 回答 (7件)

char *p = new char[SIZE];


で確保した領域を
memset( p, 0, 何らかのサイズ );
としても危険はありません。
処理系にも依存しません。

これは配列の要素が汎整数型だからです。
非POD型の場合は危険ですし、POD型の場合でも、ポインタ型や浮動小数点型、またはそれらを含む集成体の場合も安全とはいえません。

型によって、安全であったり、そうでなかったりするので、よく分からないならmemsetは使わない方が無難です。
最低限std::fill_nを使うようにしましょう。
なお、もっとも安全なのは、そもそもnewを使うのはやめてstd::vectorにすることです。std::vectorを使えば、SIZEを持ちまわってどうこうという問題もなくなります。
    • good
    • 0
この回答へのお礼

>memset( p, 0, 何らかのサイズ );
>としても危険はありません。
"何らかのサイズ"がSIZE以上の場合には
危険ではないでしょうか?

>std::vectorを使えば、SIZEを持ちまわってどうこうという問題もなくなります。
vectorの場合は生成と同時に初期化されるということですね。

お礼日時:2008/09/18 00:37

リクツを言えば、


char *p = new char[SIZE];
で確保した領域を
memset( p, 0, 何らかのサイズ );
とするのは、こわいです。
処理系が変われば、どのような結果になるかわかりません。

率直に
for( i = 0; i < SIZE; i++ ) p[ i ] = 0;
なら、間違いありません。
    • good
    • 0
この回答へのお礼

>memset( p, 0, 何らかのサイズ );
>とするのは、こわいです。
確かにご指摘のとおり、
"何らかのサイズ"によっては
簡単にオーバーフローしますね。
ご指摘ありがとうございます。

お礼日時:2008/09/18 00:32

> 個人的にSIZEを指定してしまうのが


> キレイではないような気がしています。
なぜですか?
確保したSIZE分クリアしなければならないのだから、
SIZEを渡すことはむしろ当然のことと思いますが?

>memset(p[i], 0x00, sizeof(p[i]));
既に出ていますが、p[i]はポインタ型では有りません。
上記はchar1個に対してmemsetを呼び出す大変無駄なコードです。
こんなことをするくらいなら p[i] = 0;の方が遥かにましでしょう。

まずは、char p[SIZE];で宣言されたpと
char* p;で宣言されたpの違いを理解してください。

前者の型は char[SIZE]型のpで、後者はchar*型のpです。
故に前者でのsizeof(p)はchar[SIZE]分のサイズなのに対し
後者のpではchar*分のサイズとなります。

C言語上では配列の先頭は暗黙の変換によりchar*となりますが、
関数呼び出しなどで渡された物を除き、宣言されたスコープの中では
宣言された型を保持します。

今回はC++なのかnewが使われていますが、
C言語であれば、確保した領域の0クリアが保障されている
callocなどもあります。
    • good
    • 0
この回答へのお礼

>SIZEを渡すことはむしろ当然のことと思いますが?
初心者ながらsizeof(...)で指定できたほうがコード修正が楽になる場合もあると思い、何か方法があれば。。。という気持ちで質問させていただきました。

>前者の型は char[SIZE]型のpで、後者はchar*型のpです。
>故に前者でのsizeof(p)はchar[SIZE]分のサイズなのに対し
>後者のpではchar*分のサイズとなります。
理解していたはずなのですが、この説明はすごくわかりやすいです!
char[SIZE]型であると理解できれば当然のことですね。
根本的な考え方が間違っていたんですね。
ご指摘、有難うございます。

お礼日時:2008/09/18 00:28

> for (int i = 0; i < SIZE; i++){


> memset(p[i], 0x00, sizeof(p[i]));
> }
> では、コンパイルエラーが出てしまいます。

p[i]がポインタではないので第一引数でargument mismatchを起してるだけでしょう。
&p[i]でないと。
    • good
    • 0
この回答へのお礼

少し混乱してました。
ご指摘いただいたとおりの方法で問題ありませんでした(汗)
有難うございます。

お礼日時:2008/09/18 00:22

pがchar*型である限り、それが指している領域のサイズは


コンパイラにはわからないので、初期化時にSIZEを再指定する
しかないでしょう。

stdライブラリが使えないのであれば、
次のようにchar[SIZE]をクラス化してしまう
手もあると思います。

class char_array{
public:
char_array() {memset(c,0,sizeof(c));}
char c[SIZE];
};

char_array *p = new char_array();
    • good
    • 0
この回答へのお礼

よく分かりました!
クラス化してしまいコードを簡略化してしまう方法ですね。
有難うございます。

お礼日時:2008/09/18 00:21

newを使って配列を直接割付けなければならない理由があるのでしょうか?


特別な理由がなければstd::vectorを使う方が得策です。

コンパイラが古いとか、Embedded C++だとか、フリースタンディング環境だとか、その他諸々の組込み向けの方言だとかであれば仕方ないでしょうが...
    • good
    • 0
この回答へのお礼

vector<char> p(SIZE);ですね。
初心者なので教えてほしいのですが、1つの文字列のための領域を確保するときにでも普通はあまりnewは利用しないのでしょうか?
明示的にdelete操作できるのがnewの良さかなと思っていたのですがそういったことは経験上なかったでしょうか?(回答を拝見するとなさそうですが。。。)

お礼日時:2008/09/18 00:19

>のほかに方法はありますでしょうか?


std::fill_n()
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
試してみます!

お礼日時:2008/09/17 23:48

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています


おすすめ情報