register指定子
引用from: http://www.geocities.jp/ky_webid/c/051.html
registerを付けた変数には、高速にアクセスできるようにコンパイラに要求を出します。要求を出すだけであって、コンパイラがそれに従うかどうかは分かりませんし、どのような方法で高速アクセスを実現するかも分かりません。通常は、CPUに存在するレジスタという記憶領域に変数の値を割り当てます。レジスタはメモリよりも高速にアクセスできます。ここからregisterという名前になりました。
この指定子も、わざわざ付ける必要はありません。なぜなら、コンパイラは自動的にこのような最適化を施してくれるからです。つまり、registerを付けても高速になるとは限らないし、付けなくても高速になるかも知れないということです。
なお、registerを付けた変数のアドレスは取得できません。アドレスとは、メモリ上の番地であり、レジスタに番地はないからです。よって、ポインタ変数にregisterは付けられません。また、グローバル変数や静的変数に registerを付けることはできません。レジスタの個数には制限があり、これらの変数はプログラム実行中、常に存在しなくてはならないため、レジスタが埋まってしまうからです。
以前、O(最適化オプション)をつけないでgccでコンパイルした単純なテストプログラムのバイナリと、そのプログラムのアセンブルソースを自分で改良したバイナリの速度比較を行いました。
http://ikda.net/fswiki/wiki.cgi?page=%B7%D7%BB%BB%B5%A1%B2%CA%B3%D8%A4%E2%A4%C9%A4%AD
そのときは2倍くらい早くなったわけです。
妄想の域を出るものではありませんが、レジスタと一次キャッシュの速度の差ということでしょうか?
で、なんでこのregister指定子の話にまたなったのかというと、MySQLのparserのコード中に、register指定子が使われているのを見つけたからです。
case 800: #line 4373 "sql_yacc.yy" { if (!(yyvsp[-2].symbol).symbol->create_func) { my_error(ER_FEATURE_DISABLED, MYF(0), (yyvsp[-2].symbol).symbol->group->name, (yyvsp[-2].symbol).symbol->group->needed_define); YYABORT; } (yyval.item)= ((Item*(*)(void))((yyvsp[-2].symbol).symbol->create_func))(); } break;
parserのコードではこの"case 800:"のように、かなり巨大な"switch-case"文が使用されています。となると結構、このswitch対象の変数"yyn"にアクセスが集中すると思うのですが、
register int yystate; register int yyn;
こんな感じでregister付きの宣言をしています。
なんだかんだで、parserのコード読書率が上昇中。。。いちばん手を出したくない部分なんだけど(涙 しかしここを見ないと処理の振り分けが分からん=3 SPとかSPとかSPとかw
とかいう前置きをしたところで、今日言いたいのは〜〜〜
“ビルコレさん、新色のニンテンドーDS Lite欲しい!”