2016/08/16

[c/c++]私のC言語 (2)

第2回 よく使う型

最近、特にコンパイルオプションの指定や、コンパイラの指定もされないことが多いので、C99でやっている。
というと詳しい人のように見えるが、「//でコメントしてもよい」とか「boolやuint8_tを使ってもよい」程度だ。

 

私にとってC99がうれしかったのは、uint8_tみたいにビット幅指定の型ができたことだ。
自分でtypedefするのも面倒だし。

組み込みの人だと、intは使わず幅を固定するという人が多いのですが、私はけっこう適当です。
intはコンパイラがうまいことサイズを決めてくれるはずなので、ループのような一時的な変数だったり、メモリがある環境でフラグ変数を用意するときなんかは、ときどきintを使っている。

それだったらstdint.hにあるint_fastN_t系を使えばいいじゃないか、と言われそうで、それはそうなのだが。。。
うん、めんどうなのだ。

 

なんか、移植性を考慮してもねぇ、ということが多くて。
マイコンは32bitばかりだし、他の環境で動くアプリじゃないとなると、あまり人間ががんばらない方がいいんじゃないか、と思ったのです。
以前使っていたマイコンが、符号付き/符号無しで変換命令があるタイプだったので、悩むくらいだったらintにしとこう、と。

最近はマイコンが速いし、メモリもそこそこ多いので、難しいことをしなくても動くのが助かるところ。
普段たいへんなんだから、こういうところは楽をしたいのだ。
回らない可能性があるならlongとかにしとけばいいや、くらいな。

intにしておけば、とりあえず一番速くなるサイズを選んでくれる。
くれるはず。。。はずだよね?


気になったので、int_fastN_t系のサイズをcygwin64 gccで見てみた(unsignedも同じサイズだった)。

int_fast8_t : 1
int_fast16_t : 8
int_fast32_t : 8
int_fast64_t : 8
int : 4

・・・。
K&R本では「通常ホスト計算機の自然な整数サイズ」とあるのに、話が違うじゃないか。
「自然=一番扱いやすい」と思っていたけど、そうじゃないということか?
まあ、32bit環境だったら16と32とintは4バイトになりそうだけど。

そして、int_fast8_tは1バイトなんだ。。
私のイメージでは、CPUの汎用レジスタのサイズが一番扱いやすいサイズなのだ。
だから、16~64までが8バイトなのはまだよいのだが、それだったらint_fast8_tも8バイトになってほしかったのだ。

 

よく使っているARMだとどうかと思って検索したが、int_fast8_tはint8_tのtypedefになるようなので、やはり1バイトだ。
じゃあ、アセンブラレベルで見たらどう違うんだろう、とarm-none-eabi-gccで見てみたが、uint_fast8_tの変数でもuint_fast32_tの変数でもコードに違いがない。

自動変数だからかと思い、ポインタにしてメモリ書込にしたのだが、やはりコードに違いがない。
最適化されて消えているわけでもなさそうなのだが、8bit分の書込みと32bit分の書込みは、さすがに違うんじゃないかと思うのだが、何か書き方が悪いんだろうか。。。

あ、fastじゃない型名にしたら差が現れた。
32bitだとstrだが、8bitだとstrbになる。。。

ああ、さっきネットで検索したint_fast8_tはLLVMのものだったけど、インストールしているarm-none-eabi-gccのstdint.hを見るとこうなっていた。

#ifdef __INT_FAST8_TYPE__
  typedef __INT_FAST8_TYPE__ int_fast8_t;
  typedef __UINT_FAST8_TYPE__ uint_fast8_t;
#define __int_fast8_t_defined 1
#elif __STDINT_EXP(INT_MAX) >= 0x7f
  typedef signed int int_fast8_t;
  typedef unsigned int uint_fast8_t;
#define __int_fast8_t_defined 1
#endif

当たり前だけど、幅を固定したいのにfastとかleast系の型を使ってはいかん、ということだ。
そして、ARMにはバイトアクセス命令があるから、1バイトアクセスしても負担はない、ということか。

だから、私が思ってた「intを使っておけば最速」というのは、そう一概にも言えないよ、となる。
8bit以内だったら、intでもuint8_tでも速度としては同じになるから、自動変数だったらそこまでこだわらなくてよいけど、グローバルで持っておくんだったらuint8_tでもよいだろう。
まあ、アラインメントもあるから、多少うまく並べた方がよいとは思うが。


[c/c++]私のC言語 (1)

0 件のコメント:

コメントを投稿

コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。