• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:自作のprintf関数で%dの整数が出力できない)

自作のprintf関数で%dの整数が出力できない

このQ&Aのポイント
  • H8S2368の基板で使用していなかったSCI0のUARTに新たに追加したprintf関数で整数が正しく出力されない問題が発生しています。
  • printf関数を使用して文字列を出力する場合は正常に動作していますが、整数を出力する場合は予期しない値が表示されます。
  • どのように改善すれば正しい整数値が出力されるようになるのか、アドバイスをいただきたいです。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.3

unsigned long v; (略) v = (unsigned long)va_arg(args, long); switch (*p) { case 's': outs_sci0((char*)v, c); break; case 'c': outc_sci0((char)v, c); break; case 'd': case 'o': case 'x': outn_sci0(*p, v, c); } を char *vp; int vi; char vc; (略) switch (*p) { case 's': vp = (char *)va_arg(args, char *); outs_sci0(vp, c); break; case 'c': vc = (char)va_arg(args, char); outc_sci0(vc, c); break; case 'd': case 'o': case 'x': vi = (int)va_arg(args, int); outn_sci0(*p, vi, c); } にせんといかんよ。 何故なら mprint_test_sci0("test value %d %d %x %x \n\r",1,1,1,1); ってやると、可変引数の「1,1,1,1」は「16ビットのintが4つ渡される」から。 なお、%d、%o、%xは、今はint(16ビット幅。0~65535)までしか出力できないから char *vp; int vi; long vl; char vc; bool lf; (略) if (*p == '%') { lf = false; p++; if ((*p >= '1') && (*p <= '9')) { c = *p++ - '0'; while ((*p >= '0') && (*p <= '9')) c = c * 10 + (*p++ - '0'); } else if (*p == 'l') { p++; lf = true; } else c = -1; switch (*p) { case 's': vp = (char *)va_arg(args, char *); outs_sci0(vp, c); break; case 'c': vc = (char)va_arg(args, char); outc_sci0(vc, c); break; case 'd': case 'o': case 'x': if (lf) { vl = (long)va_arg(args, long); outn_sci0(*p, vl, c); } else { vi = (int)va_arg(args, int); outn_sci0(*p, vi, c); } } とか、新たに「longバージョンの%ld、%lo、%lx」とか作って、呼び出す際に mprint_test_sci0("test value %d %ld %x %lx \n\r",1,1L,1,1L); とやって「可変引数に渡した数字はlongであることを明記」してやれば、long型も使える筈。 なお、この改造は「デバッグしてない」ので、バグっているかもしれない。 プログラムを直さないで、今のまま使うなら mprint_test_sci0("test value %d %d %x %x \n\r",1L,1L,1L,1L); とか mprint_test_sci0("test value %d %d %x %x \n\r",(long)a,(long)b,(long)(a + 4),(long)(a + b)); とかって感じで「数値の引数は必ずlongで渡す」ってやれば良い。

techhouse
質問者

お礼

回答頂きありがとうございます。 詳細なサンプルコード頂き大変助かります。 コードを参考にさせて頂き、修正しました。 https://github.com/KenjiMaehara/ios_apply_test/blob/20150720_test/H8S2368_console/console/console.c 次のように"mprint_test_sci0"での出力結果で数値が出るようになりました。 (コード例) mprint_test_sci0("test test3: %d %d %d %x \n\r",1,1,1,1); mprint_test_sci0("test test4: %d %d %d %x \n\r",1,2,3,4); mprint_test_sci0("test test5:"); for(k=0;k<16;k++) { mprint_test_sci0("%d,",k); } mprint_test_sci0("\n\r"); mprint_test_sci0("test test6:"); for(k=0;k<16;k++) { mprint_test_sci0("%x,",k); } mprint_test_sci0("\n\r"); (出力結果) test test3: 1 1 1 1 test test4: 1 2 3 4 test test5:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, test test6:0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f,

すると、全ての回答が全文表示されます。

その他の回答 (3)

  • tadys
  • ベストアンサー率40% (856/2135)
回答No.4

確かめていないので間違えているかもしれませんが、次のように確認してください。 mprint_test_sci0("test value %d %d %d %x \n\r",1,2,3,4);の部分を次のように変えてテストして見てください。 double a=1.0; double b=2.0; double c=3.0; int x=4; mprint_test_sci0("test value %d %d %d %x \n\r",a,b,c,x); たぶんこれで希望通りに出力されるでしょう。 これでよかったら、次を確認してください。 mprint_test_sci0("test value %d %d %d %x \n\r",(double)1,(double)2,(double)3,4); これもうまくいくでしょう。 可変引数を持つ関数の場合コンパイル時に引数の型チェックを行うことが出来ないので型が合わない記述をしてもコンパイルエラーが出ません。 こちらを参考に http://blog.kazuhooku.com/2014/12/c.html 一度、使用している開発環境で使用している変数のサイズがどうなっているのか、関数の引数がどのような形で渡されているのかを調べておくのが良いです。 私が経験した者にはdoubleとfloatが同じサイズだったり、charとintが16ビットだったりするものが有りました。

techhouse
質問者

お礼

回答頂きありがとうございます。 サンプルコード頂き大変助かります。 コードを参考にさせて頂き、修正しました。 https://github.com/KenjiMaehara/ios_apply_test/blob/20150720_test/H8S2368_console/console/console.c 次のように"mprint_test_sci0"での出力結果で数値が出るようになりました。 (コード例) mprint_test_sci0("test test3: %d %d %d %x \n\r",1,1,1,1); mprint_test_sci0("test test4: %d %d %d %x \n\r",1,2,3,4); mprint_test_sci0("test test5:"); for(k=0;k<16;k++) { mprint_test_sci0("%d,",k); } mprint_test_sci0("\n\r"); mprint_test_sci0("test test6:"); for(k=0;k<16;k++) { mprint_test_sci0("%x,",k); } mprint_test_sci0("\n\r"); (出力結果) test test3: 1 1 1 1 test test4: 1 2 3 4 test test5:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, test test6:0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f,

すると、全ての回答が全文表示されます。
  • trapezium
  • ベストアンサー率62% (276/442)
回答No.2

va_arg() の使い方がおかしくないですか? > v = (unsigned long)va_arg(args, long); じゃなく、それぞれの型に合わせて取り出さないと、 outs_sci0((char*)va_arg(args, char *), c); outn_sci0(*p, (unsigned long)va_arg(args, int), c); みたいに。 こういう汎用ルーチンは他のテストしやすい環境でテストしてみてもいいです。実際の文字出力のとこはラップしておく必要はありますが。

techhouse
質問者

お礼

回答頂きありがとうございます。 詳細なサンプルコード頂き大変助かります。 コードを参考にさせて頂き、修正しました。 https://github.com/KenjiMaehara/ios_apply_test/blob/20150720_test/H8S2368_console/console/console.c 次のように"mprint_test_sci0"での出力結果で数値が出るようになりました。 (コード例) mprint_test_sci0("test test3: %d %d %d %x \n\r",1,1,1,1); mprint_test_sci0("test test4: %d %d %d %x \n\r",1,2,3,4); mprint_test_sci0("test test5:"); for(k=0;k<16;k++) { mprint_test_sci0("%d,",k); } mprint_test_sci0("\n\r"); mprint_test_sci0("test test6:"); for(k=0;k<16;k++) { mprint_test_sci0("%x,",k); } mprint_test_sci0("\n\r"); (出力結果) test test3: 1 1 1 1 test test4: 1 2 3 4 test test5:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, test test6:0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f,

すると、全ての回答が全文表示されます。
  • trytobe
  • ベストアンサー率36% (3457/9591)
回答No.1

昔ながらの FILE構造体としてストリームを準備して、fprintf 関数でそのストリームに流し込むようにしていないから、printf の表示形式指定の構文解析機能まで実装しないといけなくなっているだけ、ではありませんか。 fprintf FILE stdout stdprn - Google 検索 https://www.google.co.jp/search?q=fprintf+FILE+stdout+stdprn つまり、昔プリンタドライバに FILE *stdprn へ fprintf していたように、FILE *sci0 を準備すべくドライバを書くほうが printf でも puts でも putchar でも最下層レベルでサポートできる。

techhouse
質問者

お礼

回答頂きありがとうございます。 詳細なサンプルコード頂き大変助かります。 コードを参考にさせて頂き、修正しました。 https://github.com/KenjiMaehara/ios_apply_test/blob/20150720_test/H8S2368_console/console/console.c 次のように"mprint_test_sci0"での出力結果で数値が出るようになりました。 (コード例) mprint_test_sci0("test test3: %d %d %d %x \n\r",1,1,1,1); mprint_test_sci0("test test4: %d %d %d %x \n\r",1,2,3,4); mprint_test_sci0("test test5:"); for(k=0;k<16;k++) { mprint_test_sci0("%d,",k); } mprint_test_sci0("\n\r"); mprint_test_sci0("test test6:"); for(k=0;k<16;k++) { mprint_test_sci0("%x,",k); } mprint_test_sci0("\n\r"); (出力結果) test test3: 1 1 1 1 test test4: 1 2 3 4 test test5:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, test test6:0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f,

すると、全ての回答が全文表示されます。

関連するQ&A