マイコンにて、
C言語で浮動小数点の数値を表示するプログラムを作成しているのですが、
PRINT_OUT("123.456");
のように、文字列を直接指定した場合は正しく表示されるのですが、
sprintf()関数を用いて、浮動小数点を文字列に変換した場合、
buf char[10];
sprintf(buf,"%lf",123.456);
PRINT_OUT(buf);
とした場合はプログラムが暴走?(恐らく配列破壊を起こしていると
思われますが、)してしまい、上手く動作しません。
(但し、整数の場合は正常に動作します。)
そこで、質問させていただきたいのですが、
"123.456"のように直接文字列を指定した場合と、浮動小数点123.456
をsprintf()関数を用いて文字列に変換した"123.456"の書式に何か
違いはあるのでしょうか?よろしくお願い致します。
No.1ベストアンサー
- 回答日時:
> sprintf(buf,"%lf",123.456);
まず、double型の書式指定は %lf ではなく %f です。
%lf を使った場合の動作は未定義ですので、何が起こっても不思議ではありません(C99対応の場合はOKです)。
また、PRINT_OUT関数の仕様が不明ですので、もしかするとそこに原因があるのかもしれません。
参考URL:http://www.kijineko.co.jp/tech/superstitions/pri …
この回答への補足
>>まず、double型の書式指定は %lf ではなく %f です。
>>%lf を使った場合の動作は未定義ですので、何が起こっても不思議では
>>ありません(C99対応の場合はOKです)。
そうだったのですね。%lfが標準だと勘違いしていました。
参考URLが参考になります。ありがとうございます。
>>また、PRINT_OUT関数の仕様が不明ですので、もしかすると
>>そこに原因があるのかもしれません。
PRINTOUT関数をもう少し調べてみます。
No.5
- 回答日時:
H8ですね。
残念ながらルネサスはSH2とR8Cしか経験が無いんで経験からの話は出来なさそうです。結果を見る限り、私もsprintfの浮動小数点の実装が心配ですね。
bufの内容を1バイトづつターミナルに表示させてみてはどうでしょう。
sprintf(buf,"%lf",123.456);
for( i=0; i<20 ; i++ ) {
char dump[10];
sprintf(dump,"%02x:%c\n",buf[i],buf[i]));
PRINT_OUT(dump);
}
こんな感じで。
この回答への補足
>>sprintf(buf,"%lf",123.456);
>>for( i=0; i<20 ; i++ ) {
>>char dump[10];
>>sprintf(dump,"%02x:%c\n",buf[i],buf[i]));
>>PRINT_OUT(dump);
>>}
bufの内容を1文字ずつ表示するこちらの方法も試してみたいと思います。
ご助言、ありがとうございます。
No.4
- 回答日時:
おそらく暴走の原因は#2で指摘されている配列要素数の不足が原因でしょうね。
ただ、書式指定が間違っていると、本当に暴走してしまう実装も組み込みではときどき見かけます。また、sprintf関数自体がフリースタンディング環境ではサポートされないため、浮動小数点数が使えないことも普通にあったりします(浮動小数点周りのランタイムをリンクすると、非常にプログラムサイズが大きくなるので)。
その辺りも問題がないか調べてみてください。
PRINT_OUTに関しては、関数またはマクロの定義をよく調べることと、
char buf[] = "123.456";
PRINT_OUT(buf);
としたときに期待した結果になるかどうかを調べて、問題を切り分けることをお勧めします。
この回答への補足
>>ただ、書式指定が間違っていると、本当に暴走してしまう実装も
>>組み込みではときどき見かけます。また、sprintf関数自体がフリー
>>スタンディング環境ではサポートされないため、浮動小数点数が
>>使えないことも普通にあったりします(浮動小数点周りのランタイムを
>>リンクすると、非常にプログラムサイズが大きくなるので)。
そうですか。書式設定辺りに注意が必要そうですね。
また、確かにライブラリを読み込むとプログラムサイズが一気に大きくなりました。
>>char buf[] = "123.456";
>>PRINT_OUT(buf);
こちらの方法も試してみたいと思います。
ご助言、ありがとうございます。
No.3
- 回答日時:
shirayukixさんへ。
マイコンですのでprintfは実装されていないか、特殊関数を用意しないと使えないと思います。
PRINT_OUT()がUARTを制御していてRS232Cの通信経由でターミナルソフトに文字列を表示する良くある仕組みだと思います。
暴走の原因は、shirayukixさんの言われる通り配列破壊で間違いないでしょう。
linuxbeginnerさんへ。
文字列は、文字列終端'\0'までを含んだ配列サイズを確保してください。
いちいち何文字か気にしているのが面倒であれば余裕を見たサイズで確保しましょう。
名前にLinuxとありますが、Linuxが乗るような32bitマイコンならメモリサイズの余裕があると思いますが。いや、その前にLinuxが乗っているならprintfぐらい使えるようになっているはずだから・・・。もっと小さいマイコンか?
この回答への補足
>>文字列は、文字列終端'\0'までを含んだ配列サイズを確保してください。いちいち何文字か気にしているのが面倒であれば余裕を見たサイズで確保しましょう。
今後は、余裕を持たせて取ることにします。
しかし、今回、サイズを20に変更したのですが、暴走は止まりましたが、
PRINT_OUT()関数で全く表示がされませんので、PRINT_OUT()関数に原因がありそうです。
整数値なら正常に表示されるのが謎ですが。
>>名前にLinuxとありますが、Linuxが乗るような32bitマイコンなら
>>メモリサイズの余裕があると思いますが。いや、その前にLinuxが
>>乗っているならprintfぐらい使えるようになっている
>>はずだから・・・。もっと小さいマイコンか?
使用しているのはH3048という16[bit]のマイコンです。
名前には、Linuxとありますが、これはユーザ登録した当初はLinuxを使って
いたためであり、今回の質問の件とは関係がありません。ややこしくてすいません。
No.2
- 回答日時:
%lfを使うと結果の小数点以下は6桁になります。
123.456000
sprintfでbufに格納すると末尾の'\0'を含めて11文字になりますからbufの長さ10文字を超えます。
なので配列破壊を起こしていると思います。
sprintfを使う前に、printfで出力してみてはどうでしょうか?
この回答への補足
>>%lfを使うと結果の小数点以下は6桁になります。
>>123.456000
>>sprintfでbufに格納すると末尾の'\0'を含めて11文字になりますから
>>bufの長さ10文字を超えます。なので配列破壊を起こしていると思います。
やはり、配列破壊の可能性が高そうですね。
bufのサイズを20に変更した所、暴走はなくなりましたが、
PRINT_OUT関数で全く表示がされていないようです。
>>sprintfを使う前に、printfで出力してみてはどうでしょうか?
これに関しては、マイコン上では、直接指定はできないのですが、
試しにWindows上で試してみたところ、正常に動作はしているみたいです。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Excel(エクセル) エクセル関数の変わった使い方 3 2022/05/13 17:12
- C言語・C++・C# c言語 コマンドライン引数 4 2023/02/09 18:47
- Java Java 南京錠 2 2023/02/04 11:46
- Visual Basic(VBA) VBAで、特定の文字より後を削除して残った数値を文字列に変換と特定の文字より前も削除したい 3 2022/04/15 19:21
- Visual Basic(VBA) VBA初心者です 検索した数字の行に色をつける 5 2023/02/13 14:22
- C言語・C++・C# sprintf()の使い方について 1 2022/08/17 16:16
- C言語・C++・C# C言語初心者 構造体 課題について 2 2023/03/10 19:48
- Visual Basic(VBA) EXCEL VBAで教えてください。 1 2022/12/22 04:20
- その他(プログラミング・Web制作) pythonのプログラムについての質問です。 1 2023/05/26 10:31
- Visual Basic(VBA) 【再々投稿】VBAのプログラムで動作しなくて困っています 8 2022/10/14 09:06
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・プリン+醤油=ウニみたいな組み合わせメニューを教えて!
- ・タイムマシーンがあったら、過去と未来どちらに行く?
- ・遅刻の「言い訳」選手権
- ・【大喜利】【投稿~11/12】 急に朝起こしてきた母親に言われた一言とは?
- ・好きな和訳タイトルを教えてください
- ・うちのカレーにはこれが入ってる!って食材ありますか?
- ・好きな「お肉」は?
- ・あなたは何にトキメキますか?
- ・おすすめのモーニング・朝食メニューを教えて!
- ・「覚え間違い」を教えてください!
- ・とっておきの手土産を教えて
- ・「平成」を感じるもの
- ・秘密基地、どこに作った?
- ・【お題】NEW演歌
- ・カンパ〜イ!←最初の1杯目、なに頼む?
- ・一回も披露したことのない豆知識
- ・これ何て呼びますか
- ・初めて自分の家と他人の家が違う、と意識した時
- ・「これはヤバかったな」という遅刻エピソード
- ・これ何て呼びますか Part2
- ・許せない心理テスト
- ・この人頭いいなと思ったエピソード
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・ハマっている「お菓子」を教えて!
- ・【大喜利】【投稿~11/1】 存在しそうで存在しないモノマネ芸人の名前を教えてください
- ・好きなおでんの具材ドラフト会議しましょう
- ・餃子を食べるとき、何をつけますか?
- ・あなたの「必」の書き順を教えてください
- ・ギリギリ行けるお一人様のライン
- ・10代と話して驚いたこと
- ・つい集めてしまうものはなんですか?
- ・自分のセンスや笑いの好みに影響を受けた作品を教えて
- ・【お題】引っかけ問題(締め切り10月27日(日)23時)
- ・大人になっても苦手な食べ物、ありますか?
- ・14歳の自分に衝撃の事実を告げてください
- ・【大喜利】【投稿~10/21(月)】買ったばかりの自転車を分解してひと言
- ・ホテルを選ぶとき、これだけは譲れない条件TOP3は?
- ・家・車以外で、人生で一番奮発した買い物
- ・人生最悪の忘れ物
- ・【コナン30周年】嘘でしょ!?と思った○○周年を教えて【ハルヒ20周年】
- ・あなたの習慣について教えてください!!
- ・都道府県穴埋めゲーム
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
%dなどの違い
-
プログラムによく出てくるst...
-
C++で入力した文字列から数字を...
-
WSH(VBS)でJSONの文字列を読み...
-
nullと""、\\0とEOFの違いにつ...
-
16進数を2文字ずつ配列に格納し...
-
VBA-DLLの引数受け渡しについて
-
Shift_JIS(16進)を文字に変換す...
-
シリアル通信で0x00を送信した...
-
C言語 配列の長さの上限
-
関数から配列を返すには?
-
C言語のポインタに直接アドレス...
-
VBAのプログラムで、DIAG = 1# ...
-
「#undef」と「#define」の使い...
-
Integer変数をカラにしたいので...
-
構造体のextern方法
-
セグメントエラー
-
CStringからchar*への型変換に...
-
C言語の課題が出たのですが自力...
-
配列を含む構造体の初期値について
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
プログラムによく出てくるst...
-
nullと""、\\0とEOFの違いにつ...
-
C++で入力した文字列から数字を...
-
WSH(VBS)でJSONの文字列を読み...
-
C#でstringをポインタとして渡す
-
TCL言語で文字列検索方法を教え...
-
%dなどの違い
-
VB6.0でのバイナリデータの扱い...
-
16進数を2文字ずつ配列に格納し...
-
[C++]WCHARの1文字目しか表示で...
-
char型配列の最大要素数
-
_tcscpy_s(wcscpy_s)の第二引数...
-
シリアル通信で0x00を送信した...
-
Shift_JIS(16進)を文字に変換す...
-
sprintf関数について教えて下さ...
-
バイナリファイル中の日本語文...
-
構造体→文字列→構造体 をする方法
-
引用符と二重引用符
-
C言語の勉強しています。すみま...
-
文字列にある特定文字の数
おすすめ情報