質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

4回答

1880閲覧

C言語 長いプログラムのスマートなプログラムリセット(終了)方法について教えて下さい。

Guamstreet

総合スコア31

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

1クリップ

投稿2017/11/22 12:49

編集2017/11/23 08:25

MPLAB_X IDEと、XC8コンパイラの組み合わせ環境です。

PIC16F1938を使用し、普段はスリープさせておいて、外部割り込み(RB0)を意図的に発生させる事でスリープから復帰。
そして割り込みプログラムにて、希望の動作をさせると言ったフローでプログラムを製作したいです。

その割り込みプログラムの最初で、条件分岐をさせ、①次のプログラムに進むか、もしくは、②プログラムを終了させて、また、改めてスリープに戻り、外部割り込みの発生を待機させると言った事をさせたいです。

この希望を実現させる為に、普段は『goto』を使用しています。
条件YESなら、次のプログラム。noなら『goto END_PROGRAM;』と言う風にして、プログラムの最後に、一気に飛ばします。
そうすれば、また、sleepに戻り、外部割り込み発生するまで待機してくれます。

しかしながら、今回製作しているプログラムが、異常に長く、どうやら許容範囲を超えてしまったみたいで、XC8コンパイラエラーが発生。
『error~fixup overflow string~』と言うエラー文が表示されてしまいます。

そこで、プログラムのスリム化や、効率化をして、なんとか、プログラムを短くする様に努力したのですが、それでも長いみたいで、コンパイルエラーが発生し、同じエラー文が表示されます。

以上を踏まえた上で、今のプログラムの内容は変えずに、私の希望を実現させる為のスマートな方法は、どのような方法がありますか?
そこの所を、ご教示頂けると嬉しいです。

自分でも色々と考えました。

(1)exit(0);を採用する。
最初の条件に置いてnoの場合、exit(0);// 強制終了。
これで、私の希望は実現できますか?
また、exit関数利用の為の実装(stdlib.h)がなされていれば、この1命令だけで、他は何もしなくて大丈夫でしょうか?
更に、プログラムを終了して元に戻るみたいな、今回の使用の仕方としてなら、exit(0);関数は、プログラム中に2つ以上使用しても問題はないでしょうか?

(2)return(0);を採用する。
最初の条件に置いてnoの場合、return(0);// 強制終了。
これで私の希望は実現できますか?
また、return関数利用の為の実装がなされていれば、この1命令だけで、他は何もしなくて大丈夫でしょうか?
更に、私の希望するプログラム製作においては、exit、returnのどちらを採用するのが適切でしょうか?
それと、プログラムを終了して元に戻るみたいな、今回の使用の仕方としてなら、return(0);関数は、プログラム中に2つ以上使用しても問題はないでしょうか?

(3)WDTを採用する。
条件noの場合、while(1){}で永久ループを意図的に発生させ、WDTでリセットをかける事で、改めてsleepから始める。
この方法はインターネットを探して見つけました。
これをやる場合は、コンフィグも合わせて、どの様な設定をすれば宜しいでしょうか?

(4)RESET();を採用する。
これもインターネットで探しました。
データシートで、ざっと調べてみましたが、どこに記載されているのか、わかりませんでした。
もし、これを採用する場合は、具体的にどの様なソースを記述する事で希望する動作をしてくれるプログラムが作れますか?

以上4点について、この中に、今回の、私が製作している様な、長いプログラムに最適な、スマートな方法がありますでしょうか?

それとも、上記以外で、一般的に採用されているスマートな方法がありますか?

XC8コンパイラについては、現在、free版を使用してプログラミングしています。
元々、長いプログラムが原因で、許容範囲を超えてしまった為、『goto』が採用できないと言う事で、有償版に変更して最適化させ、そして『goto』で飛ばした方が、すっきりしてよろしいのでしょうか?

色々と、申し訳ありませんが、ご教示の方、どうぞよろしくお願い申し上げます。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

XC8の関数はソースファイルがインストールされているので閲覧することができます。それを参照すると、exit関数は次のようになっています。

C

1void 2exit(int v) 3{ 4 for(;;) 5 continue; 6}

一目瞭然で、ただの無限ループです。もちろんこんなのはC言語規格から言えばあり得ない実装なのですが、他のマイコン専用コンパイラーでもこうした実装はしばしば見かけますし、むしろ一般的とも言えます。

今まで回答やコメントは、こうしたマイコンプログラミング固有の特殊事情を踏まえていないものがほとんどのように思えます。

ということを昨日書きかけてやめたのですが、やっぱり書かないとまずそうな雰囲気なので。

で、それを踏まえた上なんですが、私も適切な答えはちょっと出しづらいなあ。そもそも事の発端になっているエラーメッセージが、本当に想像されている「プログラムが長くて許容範囲を超えた」通りなのかなと思うのですが、私もPICでは長らく他のコンパイラーを使っていたので、XC8のエラーメッセージの詳しい内容まではちょっとわかりかねます。

率直に言って、この質問はYahoo知恵袋の方がいいかもね。あちらにはマイコンにもPICにも通じている回答者がおられますので。

投稿2017/11/23 09:41

編集2017/11/23 09:50
keicha_hrs

総合スコア6768

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Guamstreet

2017/11/23 09:57

keicha_hrsさん、お待ち申し上げておりました。 ご回答下さり、ほんとに嬉しいです。 ビックリです。exit関数の正体がこれだなんて! 永遠ループしているだけですね(汗) これでは、私の希望は叶いませんね。 これでは、一旦、電源を落とすとか、そう言った対処しかないですね。 それにしても、keicha_hrsさんのおかげで、また一つ、知識を習得させて頂き、ほんとにうれしいです。 ありがとうございます。 keicha_hrsさんが仰られている『本当に想像されている「プログラムが長くて許容範囲を超えた」通りなのかなと思うのですが、~』と言う下りですが、どこを確認すれば、私の根拠のない見立てより、エラーの事実を認識する事ができますでしょうか? 今回もまた、付き合わせてしまって申し訳ございません。 もう一度だけ、甘えさせて頂き、それから、yahoo質問に投げてみたいと思います。
Guamstreet

2017/11/23 10:57

keicha_hrsさん、たびたびすいません、後学の為、教えて頂けないでしょうか。 今回、exit関数の中身を提示してくださいましたが、これは、どの様にして見る事ができるのですか? 教えて頂けると幸いでございます。 何度も、申し訳ございません。
keicha_hrs

2017/11/23 12:07

普通にインストールしたなら、 C:\Program Files (x86)\Microchip\xc8\v1.44\sources の下にあります。
Guamstreet

2017/11/23 12:26

keicha_hrsさん、いつも、色々すいません、ありがとうございます。 おかげさまで、また、ひとつ、知識を習得する術を、教えて頂きました。 ホントに感謝の気持ちでいっぱいです。 今回は、取り敢えず、suyamaさんという方が教えて下さった"return"でプログラムを実際に動かしてみることにします。 それでダメなら、keicha_hrsさんにアドバイス頂きましたyahooで質問してみようと思います。 ほんとに色々ありがとうございます。 実験した結果を、また、ご報告させて頂きます。 今回も、お付き合い頂きありがとうございました。
yumetodo

2017/11/23 12:31

やっぱりか!!!! うん、そんな気はしてたんだ。だから >お使いの処理系が正しくC規格に沿ってexitを実装していれば と釘を指していたんですが。 keicha_hrs氏指摘の通り、Yahoo!知恵袋のほうが詳しい回答者がいるのでそちらへ質問するか英語で本家のStackOverflowに質問されることをおすすめします。
Guamstreet

2017/12/04 13:21

keicha_hrsさん、ご連絡が遅くなりました。 return;でプログラム製作し、実際にPICにて動作させたところ、見事、return;で、元のSleep状態に戻る事が出来ました! return;は、プログラム内で、いくつ使っても大丈夫みたいでした。 色々とありがとうございました! (yahoo質問の方にも、質問を投げてみたのですが、return;でと仰ってくれる方がいらっしゃいませんでした) これで、私の問題は解決いたしましたので、本質問を終了させて頂きます。 ご報告とお礼まで!
guest

0

XC8自体使った事がないのでなんとも言えませんが、通常はreturnなりexitなりで抜ければよいはずです。
エラーになるのはそういう問題ではなく、単純にプログラムが大き過ぎてスタックが足りてないからかと思います。

もし、割込みではなくてワンショットなら動くということであれば、処理が長過ぎて多重割り込みになっているということもありえなくはないですが・・・・。(普通は先頭で割込み禁止にして、終了時に割込み再開にしますが)

投稿2017/11/23 10:01

CodeLab

総合スコア1939

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Guamstreet

2017/11/23 11:33

CodeLabさん、ご回答くださりありがとうございます。 他の回答者の方も、"return;"を試してみてはと仰って下さっているので、今回は、"return;"で、実際に実験してみようと思っています。 ご回答くださり、どうもありがとうございました。
guest

0

ベストアンサー

exitとreturnの結果が同じような動作となるのは、main関数内だけかと思います。
通常はexitにてプログラムを終了すれば事足りるかと思います。

exit
http://pubs.opengroup.org/onlinepubs/009695399/functions/_exit.html

投稿2017/11/23 08:35

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Guamstreet

2017/11/23 08:43

suyamaさん、ご回答くださり、どうもありがとうございます。 間違って理解してると、せっかくご回答くださったのに申し訳ないので、確認をさせてください。 exit(0);// 強制終了。を割り込みプログラム内に、一行だけ記述する事で、通常は、終了後、元に戻って、スリープにて、割り込み発生するまで待機と言う状態になると言う認識で大丈夫でしょうか? すいませんが、ご返信頂けると、幸いです。
退会済みユーザー

退会済みユーザー

2017/11/23 08:50

実際のコードを見ていないので確実な回答は致しかねます。 コードを記載しているのはmain関数内でしょうか? そうではなく割り込みによる関数呼び出し等をされているのであれば、プログラム全体を終了させるexitでは要件に合わない可能性もあります。 PICマイコン上にOSの実装があるかや、プログラムの呼び出しをどのように行われているかなどを提示されると、回答がつきやすいかと思います。
Guamstreet

2017/11/23 09:01

早速のご返信、ほんとうにありがとうございます。 私の製作しているプログラムは、main関数のほうには、設定とsleep命令だけにして、実際の希望する動作をしてくれるプログラムは、全てsleep後の外部割り込みプログラム(static void interrupt isr (void){ )にて処理させています。 プログラムが長い為、全て、お見せする事ができません。 部分的にはお見せできますので、もし、面倒でないと言うお気持ちならば、ご指示いただければ部分的に、提示させて頂く事は可能でございます。 今、暫く、お付き合いして頂けると、大変うれしく思います。 どうぞ、よろしくお願い致します。
退会済みユーザー

退会済みユーザー

2017/11/23 09:10

interruptを指定した関数内での処理を中断したいということであれば、その関数内で"return;"を呼び出す形になるかと思います。 最初に実行された段階で中断されるため、関数内に何度記述されてもかまいません。
Guamstreet

2017/11/23 09:23

ご返信頂き、ありがとうございます。 先程、実際にプログラムを記述し、コンパイルさせてみたのですが、 interrupt関数内で、return(0);で記述すると、エラーになってしまいます。 エラーにならないのは、 ①interrupt内の強制終了させたい所にはexit(0); ②interrupt内の最後(プログラムの最後)にreturn; と言う組み合わせです。 "(0)"がつくのと付かないのとでは、エラーが出たり出なかったりします。 今回、私が製作しているプログラムは、単純にPICの入出力を制御する様な内容的には簡単なプログラムです(一部TX送信のみ実施しています)。ただ、それが異常に長いだけです。 ですから、exitにしてもreturnにしても、引数返しの"(0)"は、suyamaさんが、ご教示くださった、"return;"だけで、元々、記述する必要が、無かったりするのでしょうか? ここの所は、いかがなものでしょうか? お付き合い頂きありがとうございます。
退会済みユーザー

退会済みユーザー

2017/11/23 09:33 編集

関数は"static void interrupt isr(void)"と定義されているので、値を返してはいけません。
Guamstreet

2017/11/23 09:30

ご回答ありがとうございます。 voidとしてしまっているから、値を返さないと言う認識でよろしいでしょうか? 例えば、voidがintであれば、値として返さなければいけないと。 この様な認識で正しいでしょうか? 基本的な質問ですいません。
退会済みユーザー

退会済みユーザー

2017/11/23 09:31

ご認識の通りかと思います。
Guamstreet

2017/11/23 09:44

敏速な回答して頂き、ほんとに助かります。 今まで、難しい演算子の使用はほとんどございませんで、LEDが付いた消えたの単純なプログラム製作をしてきましたので、先程の様な基本的な質問となってしまいました。 それにも関わらず、お答え頂き、本当にありがとうございます。 また一つ、知識を習得する事ができました。 今、ご教示頂きました所の"return;"を、割り込みプログラム中の強制終了したい所と、同じく、割り込みプログラム中のプログラム最後の部分に記述し、コンパイルさせて見たところ、エラーなしで、無事にコンパイルできました。 ありがとうございます。 ただ、一つ、疑問に思うのは、exit(0);と強制終了させたい所に、引数付きで記述しても、コンパイルエラーにならないというのは、結局、その時点で完全終了という事で、そのあとの引数を返す事さえも終了しているのだからやらないと、こんな風に捉えてもよろしいものなのでしょうか? だから、suyamaさんが、ご教示して下さった"return;"が適任と、こんな風に考えられるのですが、この辺りは如何でしょうか?
退会済みユーザー

退会済みユーザー

2017/11/23 10:05 編集

exitはプログラムの終了ですので、プログラムの終了コードを返却することに問題はありません。 main関数の定義がint mainであっても、void mainであってもです。 実際にはその終了コードを受け取って次に実行されるものが何もないため、keicha_hrsさんのご回答のように実装上は無限ループとなって何も処理を行わなくなるといった挙動となるようですね。
Guamstreet

2017/11/23 10:51

suyamaさん、ここまで色々とありがとうございました。 suyamaさん含め、色々な方の、ご回答により、今回は、予想以上の知識を習得できたように思います。 これ以降は、実際に、プログラムを走らせてみて実験してみたいと思います。 ご教示頂いた"return;"を強制終了の所と、プログラムの最後の2箇所に採用してやってみたいと思います。 少し、時間が掛かるかもしれませんが、結果は、また、ご報告させて頂きます。 ほんとに、どうもありがとうございました。
Guamstreet

2017/12/04 13:26

suyamaさん、ご連絡遅くなりました。 return;でプログラム作成し、実際にPICで動作確認をしました所、見事、return;で、私の希望を実現させる事ができました。 return;にすると、そこで強制終了させる事が出来、かつ、一番最初のSleep状態に戻ってくれました。 exit;ですと、PICの供給電源を一度落とすとか、物理的なリセットを掛けないと、最初のSleepに戻りませんでした。 今回は、return;と言う、問題解決の為の重要なトリガーを下さって、本当にありがとうございました! これで、私の問題は解決されましたので、私の質問を終了させて頂きます。 遅くなりましたが、ご報告とお礼まで!
guest

0

お使いの処理系が正しくC規格に沿ってexitを実装していれば、単にそれを呼び出すだけでいいです。

投稿2017/11/22 12:59

yumetodo

総合スコア5850

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Guamstreet

2017/11/22 15:15

yumetodoさん、早速のご回答、本当にありがとうございます。 すいません、私の理解が間違っていたら、せっかく、ご回答くださったのに申し訳ないので、確認させてください。 まず、私が記した(1)の方法で簡単に、希望が実現すると言う理解で正しいでしょうか? また、『お使いの処理系が正しくC規格に沿ってexitを実装していれば~』と記述して下さっていますが、具体的に、何をもって実装と理解すれば宜しいでしょうか? headerでしょうか? headerは、 #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include <xc.h> #include <htc.h> の5つをincludeしています。 更に、現在の私のプログラミングの製作知識というものは、どなたかが製作したプログラムの模倣から始まり、それを後で理解していくパターンです。 従って、今回のexit関数についても、正直、100%使用法を理解している訳ではありません。 ただ、MPLAB_XIDEにて、exit(0);// 強制終了。と記述すると、exitの文字が、他と同様、水色に変化し認識してくれているようにも見えます。 以上をもって、exit関数が、正しく実装されていると、そう理解して宜しいものでしょうか? 基本的な事で大変申し訳ありませんが、ご回答くださいますと幸いです。
keicha_hrs

2017/11/22 17:21 編集

思うところあってコメントしましたが、出過ぎであると思い直したので取り消します。申し訳ありません。
Guamstreet

2017/11/23 02:22

keicha_hrsさん、コメントありがとうございます。 『出過ぎであると~』なんて、とんでもございません。 むしろ、出過ぎて欲しいくらいでございます。 今までも、keicha_hrsさんの、アドバイスが、現実的に、私の希望する問題解決へ繋がっているのですから、今回も、なんでも結構ですので、コメント&アドバイスなど、頂けましたら幸いでございます。 どうぞ、よろしくお願い致します。
Guamstreet

2017/11/23 08:13

yumetodoさん、自分で調べた結果、exit関数を使用するための実装条件として、exit関数を利用する場合は、stdlib.h をインクルードする事が分かりました。 なので、私のプログラムは、先にお話しました様に、#include <stdlib.h>としてインクルードさせています。 よって、実装については完了していると理解する事ができました。 ありがとうございました。 ところで、調べている時に、exitとreturnが両方ともプログラムを終了させる事が出来る関数と知りました。 但し、return関数とexit関数の違いについて、下記の様な違いを説明してくれているサイトがありました。 以下、一部抜粋して引用。 『プログラムの動作としては、return(0);の場合は、main関数の呼び出し元に戻ってから、プログラムの終了になります。main関数の呼び出し元は、実装によると考えられますが、Cスタートアップルーチンでしょう。 exit(0);を呼び出した場合は、即座にプログラムが終了し、main関数の呼び出し元に戻らずにプログラムは終了されます。』 引用先:『https://kaworu.jpn.org/c/C言語のexit関数の使い方』 この説明の中で『プログラムの動作としては、return(0);の場合は、main関数の呼び出し元に戻ってから、~』と言う下りがありますが、これは、どの様な事を言われて居るのかが、上手く理解出来ません。 推測してみるに、これは『呼び出し元に戻る=最初に戻る』と理解しても宜しいものなのでしょうか? それに対し、exitの方は、即座にプログラム終了で元に戻らないと言う内容が書かれております。 これは『=即座に終了で、終了した所で止まったまま、なにもしない』と言う理解で宜しいでしょうか? 私の希望は、意図的にプログラム終了させた後は、また、一番最初に戻り、割り込み発生するまで待機すると言う事を、実現させるプログラムの製作です。 あと、もう一つ、exitもreturnも、プログラム中に何度使っても、大丈夫なものなのでしょうか? こちらの方も、ご教示頂けると幸いです。 引き続き、どうぞよろしくお願い申し上げます。
TaroToyotomi

2017/11/23 08:28

大雑把にいうとreturnは関数を終了する、exitはプロセスを終了するとの認識でいいかと思います。 main関数からhoge関数を呼んでいたとします。 hoge関数でreturnすると呼び出し元のmain関数に戻ってmainの続きの処理が実行されますが、exitするとmainに戻らずにプロセスが終了されます。
Guamstreet

2017/11/23 08:38

Taro Toyotomiさん、早速のご回答、どうもありがとうございます。 なるほど、そういう事なのですね。 ありがとうございます。 これを踏まえた上で、私の希望を実現させるのは、exit(0);一択と考えても宜しいでしょうか? すいませんが、ご回答くださいますと、幸いです。
TaroToyotomi

2017/11/23 09:03

お使いの環境の仕様を知らないので何とも言えませんが、 本当の意味でプログラムを終了させるのならexit(0)で問題ないと思います。 その場合、次にプログラムを実行するのは電源を入れなおした時になると思います。
Guamstreet

2017/11/23 09:10

TaroToyotomiさん、ご返信、ありがとうございます。 TaroToyotomiさん含め、皆様、色々、アドバイスして下さり、少しずつではありますが、見えてきたところがあります。 今回の質問で、ある程度、知識が蓄えられたので、そろそろ、実際に、プログラムを走らせて実験をしてみようと思います。 TaroToyotomiさん、ご助言頂き、ほんとうにどうもありがとうございます。 感謝致します。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問