![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?e8efa67)
以下のプログラムは、何回か コントロール+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です。
No.2ベストアンサー
- 回答日時:
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 …
No.4
- 回答日時:
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で終了)になるということです。
このようなことは、環境によって違うようです。
環境によって違うということを再確認できたので、ありがとうございました。
No.3
- 回答日時:
>ものすごく初歩的な勘違いだったりして。
。?前の質問の 「signalについて」
「本の説明では、~UNIXの話をしているようです。
私の環境はWindowsですが、かまわずに作って実行してみました。」
↑
このあたり。
いろいろ質問してっけど、かまわずに作ればおかしくなるよ。
話の次元が一個も噛み合わないって。
・シグナル・・・OS側から呼ばれる割り込みを擬似的にプロ
グラムから発生させる処理。
・割り込み・・・例外エラー時、無限ループ、等でOSレベル
の障害を起こさなくするための保護(むやみにいじらない)
・Windowsのシグナル・・・Windows にはシグナルの概念はあ
りません。UNIXとの互換のために仮に用意されている
だけ。完全に動作はしない
・コンソールApplication・・・DOSとの互換性のためウィ
ンドウアプリケーションを擬似的にコンソール画面にして
いるもの。OS依存
・95系・NT系・・・同じwindowsでもコンソールアプ
リケーション等はキーボード入力・プロセス割り込み等で
異なる仕様を持つ。
とりあえずこの位はさっと読んで下さい。アンタ賢そうだ
から簡単しょ。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
スーパーのレジで並んでいたら...
-
割り込み処理について
-
特殊なパターンの人見知りに悩...
-
PICのI2C通信を行っているとき...
-
Macターミナルで実行中のプログ...
-
バックグラウンドのプロセスの...
-
緯度、経度の 10進法と 60進法...
-
VBSの処理中一旦処理を止めて再...
-
コンソールアプリケーションの...
-
ソケットとそれに基づくストリ...
-
VBAの配列サイズとメモリに関して
-
【MFC】イベントの無効化について
-
TCP/IP通信時のサーバーからの受信
-
ADOでアクセスのレコードに...
-
explorer.exeが異様にメモリを食う
-
プロダクションコードとは?
-
C# シリアル通信でデータ受信...
-
【C言語】再帰が時間がかかる...
-
SQLの速度をあげるには・・・
-
ファイルマッピング関数で失敗
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
電車で待機列の割り込みについ...
-
スーパーのレジで並んでいたら...
-
USJでの割り込み
-
pic 複数の割り込み関数 切り分...
-
一定時間操作がなかったら、と...
-
Amazonfireタブレットにわから...
-
【組込み】割り込み中のstatic...
-
VB6でSendKeyを利用したTab移動...
-
CPU負荷率の安全な上限と計...
-
マイコンSH-2の割り込みを用い...
-
Excelでタイマーの一時停止する...
-
割り込み中に例外異常
-
CPUの処理量を減らすコーデ...
-
このレジの並び方は間違ってま...
-
PICのPIN変化割り込みに...
-
STATUSのZフラグについて
-
駅のトイレでナイチンに邪魔さ...
-
電車乗車時、並んでいるのに割...
-
PICマイコンでエンコーダパルス...
-
割り込み処理のシミュレート
おすすめ情報