katokenです。
本記事はACCESS Advent Calendar 2016の2日目の記事です。
あらまし
株式会社ACCESSでは、組み込み機器への自社製品のポーティングを多く手がけており、その多くはCやC++で書かれています。
昨日の記事で書いたとおり、開発中のログは基本的にfprintf()
を用いてコンソール等へ流します。
fprintf()
はフォーマット文字列を見てスタックから何バイトとってどのように文字列に変換するか決めるため、
フォーマット文字列と変数の型がマッチしていないと間違った値が表示されるどころかクラッシュすることもあります。
Question
さて、ここで問題です。
unsigned int
, void*
, size_t
, uint64_t
の型の変数の値をfprintf()
を用いてコンソールに出力したい場合、
フォーマット文字列は何を使うべきでしょうか?
Answer
答えは、以下のとおりです。
-
unsigned int
...%u
,%x
-
void *
...%p
-
size_t
...%zu
-
uint64_t
...PRIu64
マクロ (※fprintf(stderr, "%" PRIu64 "\n", (uint64_t)64);
のように使う)
みなさん安易にunsigned
型に%d
や、void*
型に%lx
、uint64_t
型に%llu
とか使っていないでしょうか?
符号が変わったり、プラットフォームのポインタサイズが変わった時にきちんと表示してくれなくなったり、クラッシュするかもしれませんよ?
終わりに
かなり短かったですが、よく使う型とそれに対応するフォーマット文字列をクイズっぽく紹介しました。
昨日の記事 のuint64_t
のタイムスタンプを出力する場合などは
プラットフォーム次第で%llu
だったり%lu
だったりするので注意です。
(Goの記事書きたかったんだけど業務都合で間に合わなかったん...)
3日目の明日は @ikeyasu さんです。お楽しみに!
参考文献
- man 3 printf
- [プログラミング言語 C の新機能] (http://seclan.dll.jp/c99d/c99d09.htm#dt19990705)