電子書籍の厳選無料作品が豊富!

以下のプログラムは、何回か コントロール+C を押すと終わる、という意図で作られています。
forから抜ける条件がいくつか書いてありますが、3とか6とかいう数字そのものには意味は別になく、とにかく、何回かで終わる、ということです。


#include <stdio.h>
#include <signal.h>

int g=0;

void onsig(int sig)
{
g++;

printf("onsigの中 g=%d\n",g);
signal(SIGINT, onsig);
}


int main(void)
{
signal(SIGINT, onsig);

for( ; g<10 ; )
{
if(g>3)break;
if(g>=6)goto owari;
}

owari:
return 0;
}


結果

onsigの中 g=1
onsigの中 g=2
onsigの中 g=3
onsigの中 g=4
onsigの中 g=5
onsigの中 g=6
onsigの中 g=7
onsigの中 g=8
onsigの中 g=9
onsigの中 g=10
onsigの中 g=11
onsigの中 g=12
onsigの中 g=13
onsigの中 g=14
onsigの中 g=15
onsigの中 g=16
onsigの中 g=17
onsigの中 g=18


こういう感じで、いつまでたっても終わりません。
onsig内で g++ をしているので、gは増えていくはずですが…
何がいけないのでしょうか。
ものすごく初歩的な勘違いだったりして。。?

VC++6.0でWin32 Console Applicationで作成しています。
Windowsです。

A 回答 (4件)

for ループの中で、g を変更していなくて、他の関数も呼び出していないことから、最適化によって、g が 10 未満ならば単純な無限ループにしてしまっているのだと思います。



volatile int g=0;

とすることで、変数 g に対して最適化をしなくなるはずです。
最適化なしでコンパイルすれば、現状のままでも終了すると思います。

この回答への補足

ご回答のとおり、最適化の問題のようです。
ありがとうございました。

=====================================
詳しく述べますと、
VC++6.0のメニューの「プロジェクト」の「設定」の「C/C++」タブで、
カテゴリ「一般」を選ぶと「最適化」というチョイスボックスがあります。

それをいろいろに変えると、質問のコードで終わるプログラムになったり、終わらないプログラムになったりします。 

#意識したことなかった。( ;^^)ヘ..

・「デフォルト」    →終わる
・「無効(デバッグ時)」→終わる
・「実行速度」     →終わらない
・「プログラムサイズ」 →終わらない
・「カスタマイズ」   →終わる
(デバッグ版では、「実行速度」・「プログラムサイズ」を選ぶとコンパイルでエラーになる。)

私は、リリース版で、最適化を「実行速度」にしていました。そのため、終わらないプログラムになっていたと考えられます。

=================================
volatile について:
ご回答どおり、volatile int g=0;  と宣言すると、最適化が「実行速度」・「プログラムサイズ」であっても、終わる。


volatile とは何なのか、ということはほとんど知らない(とりあえず、最適化を抑止する、ということらしい。)ので、自分で調べてみたいと思います。

自分のメモ用:以下が参考になるかも。
http://www.cmagazine.jp/src/kinjite/c/variable.h …

補足日時:2002/07/22 23:07
    • good
    • 0

onsig関数内のsignal関数のせいじゃないでしょうか。


signal関数は一度指定だけで、signal待ちをしますので、
再帰呼出しをする必要はありません。
そのため、この構文ではonsig内のsignalは全く必要ありません。

Linux gccではこのままでも、問題なく動くのですが、
Windows VC++では再帰待ちで親関数に戻らないのかも知れません。
僕は、Linux使いなのではずしていたらすいません。

この回答への補足

回答No.2の補足に書いたとおり、最適化の欄を適切に変えたり、volatile int g=0;  という宣言をすると、数回コントロール+Cを押すと、終わります。

その場合、
onsigの中 g=4
を表示した直後に終わります。(回答No.1も。)

でも、ご回答にあるように、onsig関数の中のsignalを削除すると、
コントロール+Cを2回押すと終わってしまいます。
1回目で
onsigの中 g=1
が表示され、
2回目は
その表示がなく、すぐに終わります。

onsig関数の中のsignalを削除すると、一回コントロール+Cを行なってしまうとコントロール+Cに対する反応がリセットされて、デフォルトの動作(コントロール+Cで終了)になるということです。

このようなことは、環境によって違うようです。

環境によって違うということを再確認できたので、ありがとうございました。

補足日時:2002/07/23 21:37
    • good
    • 0

>ものすごく初歩的な勘違いだったりして。

。?
前の質問の 「signalについて」
 
「本の説明では、~UNIXの話をしているようです。
私の環境はWindowsですが、かまわずに作って実行してみました。」

このあたり。
いろいろ質問してっけど、かまわずに作ればおかしくなるよ。
話の次元が一個も噛み合わないって。

・シグナル・・・OS側から呼ばれる割り込みを擬似的にプロ
グラムから発生させる処理。
・割り込み・・・例外エラー時、無限ループ、等でOSレベル
の障害を起こさなくするための保護(むやみにいじらない)
・Windowsのシグナル・・・Windows にはシグナルの概念はあ
りません。UNIXとの互換のために仮に用意されている
だけ。完全に動作はしない
・コンソールApplication・・・DOSとの互換性のためウィ
ンドウアプリケーションを擬似的にコンソール画面にして
いるもの。OS依存
・95系・NT系・・・同じwindowsでもコンソールアプ
リケーション等はキーボード入力・プロセス割り込み等で
異なる仕様を持つ。

とりあえずこの位はさっと読んで下さい。アンタ賢そうだ
から簡単しょ。
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。

お礼日時:2002/07/23 21:16

なぜでしょう?


同じ環境で、そのままコピぺしてやったら

onsigの中 g=4

と表示したあとにきちんと終了したのですが・・?

原因はコード以外にあるのかも?

この回答への補足

終わったそうで、、、参考になります。

補足日時:2002/07/22 22:28
    • good
    • 0

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