1. #include <stdio.h>
2. int main(void){
3. static char *wday[3]={
4. "sunday"
5. ,"monday"
6. ,"tuesday"
7. };
8. static char **p;
9. p=wday;
10. while(*p){
11. printf("%s\n",*p);
12. ++p;
13. }
14. return 0;
15. }
上記で、3行目と8行目のstaticを外すとsunday monday tuesdayの後にゴミを出力するのは何故なのか。原因と対策を知りたい。
No.3ベストアンサー
- 回答日時:
これは「staticを外すとsunday monday tuesdayの後にゴミを出力する」のではなく、「staticを付けたらたまたまうまく動いた」のです。
10行目の判定は *p が指している先が NULL の時に偽になります。*p が指している先は 9 行目で wday の先頭に設定され、12 行目でひとつづつ次の要素に移動します。
しかし、"tuesday" を指しているときに次の要素へ移動しようとしたとき、C言語では何も文句を言わずに wday の領域を超えた箇所を指してしまいます。
static を指定した時はたまたまその箇所が NULL だったのでしょう。
一番簡単な対策は、wday の宣言を以下のように変えることです。
static char *wday[4]={
"sunday"
,"monday"
,"tuesday"
, NULL
};
上記なら static を外しても意図した通りの動作になります。
有難う御座います。まさか記憶クラスの違いでエラーが出たり出なかったりする物ですから視点が泳いでいました。そこ迄は気が付きませんでした。
この辺についてはコンパイラー次第でかなりの差が有るみたいです。これから本格的に使うつもりです。この辺についてはコンパイラーのオプション次第ではかなりのエラーの精度が変わる様な指定と言うのが有るのかも知れません。
これに続いて、今後はこれを参考にしてコンパイルする時のコンパイラーのオプションにも気をつけたいと思います。
今迄はコンパイラーは通常gccを使っていましたが。余りにもコマンドラインのオプションが多いために敬遠をしていて一番簡単なパターンで起動していました。この様な事が有るので今後はきちんとオプションも見直したいと思います。
果たして本当に見直した所で正しい正解が有るのかは分かりませんが。一つの今後の私の新しい勉強のきっかけには成りました。有難う御座いました。
No.2
- 回答日時:
C言語をやる以上は、配列とポインタは必須なので、しっかり理解するようにしましょう。
char *wday[3]
で、char * 3つ分の領域が確保され、
wday[0] = "sunday" の先頭アドレス
wday[1] = "monday" の先頭アドレス
wday[2] = "tuesday" の先頭アドレス
となります。
これを
> while(*p){
で、p=&( wday[0] ),&( wday[1]), &( wday[2]) とループを続けます。
このとき、
*p= wday[0] , wday[1], wday[2]
となって、文字列のある領域へのポインタになっている、すなわち 0 ではないので、ループが続きます。
そして、
p= wday[3] となります。
さて、 char *wday[3] と宣言したときに、 wday[3] はどうなっているでしょうか?
static の場合は、たまたま wday[3]に相当する領域が 0 になっていたのでwhile ループが終了した。
staticが無い場合、たまたま wday[3]に相当する領域が 0 ではないのでループが継続し、 wday[3]の領域に書かれている何かを「アドレス」と判断して、その「アドレス」にある「文字列」を出力します。
続いて、 wday[4],wday[5]...と、 0 になるまでループを繰り返します。
※ または、途中でOSの保護領域へアクセスする等して、エラーになって止まったり、ハードディスク破壊とかも有り得ます。
対策は、「不定な領域へアクセスしないこと」です。
○ *p でループ判定するのではなく、ループ回数を指定する。
for( i=0 ; i<3; ++i ){〜 等
○最後に「終り」の印を入れる
char *wday[]={ // []の中を省略すると、指定された要素数に合せて自動で設定される
"sunday"
,"monday"
,"tuesday"
, NULL // wday[3]にNULLを指定する
};
有難う御座いました。普通の例えばchar *p="sunday"とした場合は何もnullを意識して定義はしませんよね。だから、この場合もその例に従う物と思っていました。
だから、動かない場合と言うのはこの辺のチェックも欠かせないと言う点で参考になりました。貴重な意見有難う御座いました。
No.1
- 回答日時:
staticが付いている場合、正しい動作をしているわけではありません。
たまたま、あなたの環境で、エラーが発生していないというだけです。
私の環境では、ststicを付けても正しく動作しませんでした。
(私の環境はwindows7 mingw32(4.7.2))
原因は、while(*p)で、"tuesday"の次のポインターがNULLになっていないため、
処理を終了せずに、ゴミデータを処理することに有ります。
3.char *wday[3]={
を
char *wday[4]={
として、
6.,"tuesday"の次の行に、
,NULL
を追加してください。
そうすれば、staticをはずしても正しい動作をします。(もちろん、staticを付けてもOKです)
コンパイラーはgccです。この手のサンプルでは私が書いた様な記述が有るのも事実です。また、意図してwhile文の中でnullをチェックしているのもあります。説明では、統一性と言うのは有りません。
私は最初に、sunday monday tuesdayとデータを定義した時に最後のtuesdayを定義したら次は自動的にnullを書き込むと思っていましたが。そうでは無いのですね。偶々gccでは記憶クラスがstaticの時はnullを書き込むがそうで無い記憶クラスは利用者任せと言う事でしょうか。
この辺がコンパイラー次第と言うのは互換性の件でバグが混入する危険があるのでまずいですね。然し、こう言うのは殆ど初めて触る人にとっての説明はどの本にも書いて無い様な気がします。
参考になりました。有難う御座いました。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Java java 入力 3 4 3 出力 ABC DEFG HIJ このようなプログラムの書き方を教えてくだ 2 2022/07/15 14:18
- C言語・C++・C# c言語でユーザ関数を利用して入力された文字列を反転させるプログラムを作りたいです。 3 2023/01/29 19:47
- C言語・C++・C# 宣言する関数の形が決まっている状態で、 str1とstr2の文字列をこの順に引っ付けてstrに保存し 2 2022/05/30 18:21
- C言語・C++・C# c言語配列の結合についてです。 なぜうまくいかないのでしょうか。 #include <stdio.h 4 2022/05/30 22:42
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- Java javaでのプログラム(配列)について質問です. 2 2022/10/14 22:27
- C言語・C++・C# C言語のエラーについて 2 2022/07/11 13:56
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- C言語・C++・C# バイナリファイルをコピーするのにかかる時間を測りたいのですが実行するとFatel error:gli 2 2022/11/03 01:10
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
For文の終了値を関数にしても問...
-
break文でループを一気に抜ける...
-
Excel VBAで年度をまたぐ期間の...
-
ループを途中で抜けたいのですが。
-
do-while文が禁止される理由
-
__asm int 3でのブレイクポイン...
-
C言語forループが完結した場合...
-
C言語に関する質問
-
While文の終わりにセミコロンが...
-
if文の中にfor文なのか、for文...
-
Cプログラムが終了しない
-
無限ループ対策
-
独習C 素数テスタ・・・分から...
-
入力した数値を倍々するプログラム
-
エクセルVBAで Do While (1)って?
-
入力した文字列から母音だけを...
-
他言語で言うcontinue文
-
繰り返し文の利点について
-
桁数を求めるプログラム。
-
H8/3048マイコンAD/DA変換について
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
break文でループを一気に抜ける...
-
do-while文が禁止される理由
-
ループを途中で抜けたいのですが。
-
入力した数値を倍々するプログラム
-
入力した文字列から母音だけを...
-
if文の中にfor文なのか、for文...
-
C言語forループが完結した場合...
-
エクセルでC言語のfor文と同じ...
-
Excel VBAで年度をまたぐ期間の...
-
For文の終了値を関数にしても問...
-
エクセルVBAで Do While (1)って?
-
C言語、whileループを抜け出す...
-
PAD図の書き方
-
Cプログラムが終了しない
-
PIC のプログラムについて ど...
-
他言語で言うcontinue文
-
C言語のプログラムみてください...
-
ループの特定入力終了
-
COBOLのEVALUATE文
-
for文while文の無限ループの違...
おすすめ情報