ここから本文です

memsetで0で初期化したらchar配列に変な値が入ってしまいました。 printfで出力す...

zak********さん

2014/8/302:03:14

memsetで0で初期化したらchar配列に変な値が入ってしまいました。
printfで出力すると、ヘヘヘヘと出力されます。
NULLで初期化した方がいいですか?

補足変な動きということでコードをのせます。
struct STR_LIST{
char a_str[256];
char b_str[256];
};

int main(void){
STR_LIST *str_list;
str_list = (STR_LIST *)malloc(sizeof(STR_LIST));
memset(str_list, 0x00, sizeof(str_list));
printf("a=%s,b=%s\n", str_list->a_str, str_list->b_str );
}

閲覧数:
27,443
回答数:
5

違反報告

ベストアンサーに選ばれた回答

xx_********さん

2014/8/302:38:31

念のためソースも見てみたいところですが……
例えば、

char Mojiretu[10];
memset( Mojiretu, 0, sizeof(Mojiretu) );

という感じで初期化したのなら、それは正しいやり方です。

因みに
memset( Mojiretu, NULL, sizeof(Mojiretu) );
とするのは厳密には誤りです。
NULLは 0 として代用できてしまいますが、基本的には"どこも指していないポインタ"を意味するため、上記の場合には不適切です。

なお、単にchar型配列を 0 で初期化したいのであれば、
char Mojiretu[10] = {0};
が良いでしょう。
関数コールのオーバーヘッドもないし宣言と同時に出来てソースもすっきりです。

この質問は投票によってベストアンサーに選ばれました!

ベストアンサー以外の回答

1〜4件/4件中

並び替え:回答日時の
新しい順
|古い順

プロフィール画像

カテゴリマスター

n2q********さん

2014/8/317:03:17

(1)修正内容

/*修正前*/memset(str_list, 0x00, sizeof(str_list));
/*修正後*/memset(str_list, 0x00, sizeof *str_list);

str_list は STR_LIST * 型ですね。なら、修正前の sizeof str_list というのは(あ、括弧は取りますよ、要らないので)、sizeof (STR_LIST*) と同じこと(この場合は括弧が必要)。

つまり、ポインタのサイズになってしまっていたのでした。4とか8とかっていう値になります。なので、str_list の先頭4バイトあるいは8バイトだけがゼロになっていたのですよ。

なお、お分かりだと思いますが sizeof *str_list とすることで、sizeof (STR_LIST) と同じになります。

(2)「ヘヘヘヘと出力されます」の件

これ、Visual C++ の親心(?)です。未初期化のデータだという印です。これでバグを見つけるんですよ。もしもゼロで満たされてたらって考えると、あ、大変だ。ほんとに有り難いですね。なお、未初期化のデータ領域を ヘヘヘヘ... にしてくれる(0xCD という値で満たす)のはデバッグ版だけですからね。リリース版でビルドしたら当然、未初期化となります。何が入るか分かりません。

この際、大事なことをお話したいと思います。

こうやって Visual C++ が親心で 0xCD の値をセットしているのに、せっせとそれを 0 で潰してしまっている人が一部に居ますよ。それはダメ。

/*例*/

int x = -1;
scanf("%d", &x);
if (x != -1) {
}

こういうの見た事ありますか?要するに scanf 関数から値を貰おうっていう場面ですので、x を初期化する必要は無い。未初期化のままで良い。それなのに x = -1 って何なのかな?おまじない?とぼけるのはやめときますけど、scanf で、ちゃんと値が入力されたかどうかをチェックしようっていう考えでしょう、きっと。でもそれなら if (scanf("%d", &x) == 1) これで良い。これが正しいのです。無用な、そして場合によっては有害な初期化は真似しないようにね。バグがあったときに分かりやすいように未初期化のデータを 0xCD にしてくれている Visual C++ の親切心に背く行為ですから。

返信を取り消しますが
よろしいですか?

  • 取り消す
  • キャンセル

プロフィール画像

カテゴリマスター

qui********さん

2014/8/309:33:21

少なくともNULLで初期化するのは誤りです(Cは型に甘々なのでコンパイルエラーにはならないが、論理としておかしい)。
NULLは「どこも指していないポインタ」の表現ですから、値は0であっても、処理系によっては(void*)0と定義されていることもあるくらいですから、charの初期値としては適しません。

逆に、0で初期化しようとNULLで初期化しようと、動作に違いはありませんからそれによって状況が良くなることもありません。

ソースが提示されていないので、どんな下らない間違いの可能性も考えられるのですが、
・memsetに与えるパラメータを間違えて初期化が出来ていない
・動的に配列を確保したつもりでその操作を間違えている
・初期化は出来ていても、プログラム中他の配列やポインタの扱いのミスで当該の配列の内容を破壊してしまっている
・printfに与えるパラメータを間違えている
をそれぞれ確認してみてはいかがでしょうか。

返信を取り消しますが
よろしいですか?

  • 取り消す
  • キャンセル

k03********さん

2014/8/308:41:47

zaku_ahoさん

ソースを隠さない。

pyo********さん

2014/8/306:16:17

コンパイル、実行して現象が再現するソースを載せること。

返信を取り消しますが
よろしいですか?

  • 取り消す
  • キャンセル

あわせて知りたい

この質問につけられたタグ

みんなで作る知恵袋 悩みや疑問、なんでも気軽にきいちゃおう!

Q&Aをキーワードで検索:

「テレビ録画」にまつわる困ったエピソード

みんなのアンテナ

Yahoo! JAPANは、回答に記載された内容の信ぴょう性、正確性を保証しておりません。
お客様自身の責任と判断で、ご利用ください。
本文はここまでです このページの先頭へ

「追加する」ボタンを押してください。

閉じる

※知恵コレクションに追加された質問は選択されたID/ニックネームのMy知恵袋で確認できます。

不適切な投稿でないことを報告しました。

閉じる