私はプログラミングの初心者で、C言語の勉強をしています。
まだ教科書などに書いてあるようなホントに簡単なプログラムしか書いた事が無いのですが、なんらかのゲームでも作ってC言語に慣れようと思い、数字当てゲームを作っている最中です。
そこで当てるべき数をtimeでsrandしたrand関数を使おうと考えており、まずはrand関数の振る舞いを見ようと簡単なプログラムを作ったのですがそこで自分には理解できない現象が起きてしまいました。
自分の作った簡単なプログラムのソースは
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define MAX 4
#define NO_ERROR 0

int main(void)
{
int buf[MAX-1];
int i;

srand((unsigned int)time(NULL));

/* 1:buf[0]~buf[3]にランダムな値を格納。そして毎回どんな値を格納したかを表示 */
for (i = 0; i < MAX; i++){
buf[i] = rand() % 9;
printf("buf[%d] = %d\n", i, buf[i]);
}
/* 2:4つの数字を連続で出力して4桁の数字を作る */
for (i = 0; i < MAX; i++){
printf("%d",buf[i]);
}
printf("\n");
}

と自分としては特に変哲のないように見えるのですが、実行結果が
buf[0] = 2
buf[1] = 3
buf[2] = 1
buf[3] = 3
2313
buf[0] = 4
buf[1] = 8
buf[2] = 5
buf[1] = 8
buf[2] = 5
buf[0] = 4
buf[1] = 5
buf[2] = 6
buf[8] = 1556124
4563
buf[0] = 7
buf[1] = 5
buf[2] = 0
buf[7] = -1073747000
7503
buf[0] = 1
buf[1] = 6
buf[2] = 0
buf[8] = 1556124
1603
buf[0] = 0
buf[1] = 3
buf[2] = 4
buf[1] = 3
buf[2] = 8
buf[7] = -1073747000
0383

のように1の部分が余分に表示されてしまう場合があります。
4桁の数字は出来ているので、一応無視して進んでも良いのですがどうしてもしっくりこないのでこの場で質問させていただきました。
このバグの原因は何なのでしょうか?また、どのようにすればバグの修正が出来るのでしょうか?

長文失礼しました。
よろしくお願い致します。

このQ&Aに関連する最新のQ&A

A 回答 (3件)

MAX=4のとき


> int buf[MAX-1];
で用意されるbuf[?]の?は、いくつからいくつでしょう?

C言語の配列では、用意した範囲外の値を添字に使用しても、直接はエラーになりません。
例: buf[5] で宣言して、 buf[8] とする、等
しかし、その領域には別の変数が対応していたり、通常アクセスできない領域だったりすることもあり、結果として異常な状態になることがあります。

今回の場合、bufの宣言の直後に変数iの宣言があります。そのためbuf[X]が範囲を越えた場合、まず変数iが被害を受ける可能性があります。というか、実際に受けてます。
    • good
    • 0
この回答へのお礼

>MAX=4のとき
>> int buf[MAX-1];
>で用意されるbuf[?]の?は、いくつからいくつでしょう?
あ、なるほど、そう言えばここでの宣言では配列の個数を宣言するんでしたね;
配列は[0]から始まるということを意識しすぎていました・・・

>今回の場合、bufの宣言の直後に変数iの宣言があります。そのためbuf[X]が範囲を越えた場合、まず変数iが被害を受ける可能性があります。というか、実際に受けてます。
こう言う時に宣言の順番等が関係してくるんですね。

分かりやすい解説ありがとうございます。

お礼日時:2011/04/20 11:01

「まだ教科書などに書いてあるようなホントに簡単なプログラムしか書いた事が無いのですが」


失礼な言い方になるかもしれませんが、配列の宣言と確保する領域のサイズを了解していないとすると、勉強の仕方か、参考にしている教科書の選択があまりよくない様な気がしてしまいます。
本気でC言語を身につけようとお考えでしたら、
・教科書、参考書を吟味する。配列やポインタ、構造体、共用体についてもしっかり著述されているものを選ぶ。K&Rを買うなら、「アンサーブック」も購入するなどして、フォローできるようにしておく。
・いきなりゲームプログラムに走るよりはアルゴリズムとデータ構造(探索、ソート、リスト(単方向・双方向)、トリー、平衡木)などをじっくりやったほうが後々為になると思います。その上で教科書のアルゴリズムの改善が出来ないかとかやってみたらいいのでは。

プログラムは作るのは簡単ですが、「正しく動いている」ことを挙証するのはかなり面倒です(ある入力データについては正しく動くが、特定の場合だけ誤った結果を返す、最悪クラッシュするなんてプログラム山ほどあります)。
小言のようですが、基本が大事です。少しずつでも積み重ねて立派なプログラマになってください。
    • good
    • 0
この回答へのお礼

>失礼な言い方になるかもしれませんが、配列の宣言と確保する領域のサイズを了解していないとすると、勉強の仕方か、参考にしている教科書の選択があまりよくない様な気がしてしまいます。
自分は今大学生で、情報系の授業を受けており、配列や構造体、ポインタ等は習っていたのですが、春休みで完全にボケていたようです。
「配列の宣言では個数を宣言するけど、実際に作られるのは0~宣言した個数-1になる」という所なのに、「配列は[0]から作られる」ことを意識しすぎていました。

>いきなりゲームプログラムに走るよりはアルゴリズムとデータ構造(探索、ソート、リスト(単方向・双方向)、トリー、平衡木)などをじっくりやったほうが後々為になると思います。
学校でリストについては習いましたが、他に関してはまだ勉強してないですね・・・
ちなみにアルゴリズムやデータ構造について書いてあるお勧めの本等はあるでしょうか?

丁寧に教えていただき、ありがとうございます。

お礼日時:2011/04/20 11:29

>一応無視して進んでも良いのですが



無視して進んでよいわけがありません。
プログラム完全に壊れちゃってます。

>int buf[MAX-1];

4つのデータを格納するのに3つ分しかデータエリア定義してないからです。
    • good
    • 0
この回答へのお礼

>無視して進んでよいわけがありません。
>プログラム完全に壊れちゃってます。
はい。未熟な発言失礼しました。

>int buf[MAX-1];
>4つのデータを格納するのに3つ分しかデータエリア定義してないからです。
あ、なるほど・・・
配列は[0]から始まるということに囚われていて、宣言では個数を定義する事をスッカリ失念していました。

的確なご指摘ありがとうございます。

お礼日時:2011/04/20 11:05

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


人気Q&Aランキング

おすすめ情報