2013-04-09 37 views
12

レジスタ変数の格納に関する点についていくつか説明したいと思います。 コード内でレジスタ変数を宣言した場合は、レジスタに保存されますか?C++変数をレジスタに格納する方法

#include<iostream> 
using namespace std; 
int main() 
{ 
register int i=10;// how can we ensure this will store in register only. 
i++; 
cout<<i<<endl; 
return 0; 
} 
+10

CとC++は、プログラムが実行されているハードウェアに「レジスタ」があることを保証しません。それは単にコンパイラへのヒントです。 –

+3

なぜ気になりますか? – delnan

+4

@StephenCanon C言語のヒントではなく、変数 'register'を宣言することで、そこでのアドレス指定を禁止します。 (実際にレジスタに変数を配置することについてのヒントではないかもしれません) –

答えて

28

できません。変数が頻繁に使用されることを示唆しているのは、コンパイラにとってのヒントです。ここではC99の文言があります:

ストレージクラス特異的ER registerを持つオブジェクトの識別子の宣言は、オブジェクトへのアクセスを可能な限り高速であることを示唆しています。そのような提案がどれほど有効であるかは、実装定義されています。

register指定子がそう宣言した変数は頻繁に使用されることを、実装へのヒントです:

そしてここでは、C++ 11の文言です。 [注意:ヒントは無視することができ、ほとんどの実装では、変数のアドレスが取られた場合は無視されます。この使用は廃止されました(D.2参照)。

ストレージクラスとしてregisterキーワードの使用:末端音符]実際に

registerストレージクラス指定子は、C++ 11(付録D.2)で廃止され-specifier(7.1.1)は推奨されていません。

レジスタにはアドレスがないため、Cの変数registerのアドレスは取得できません。この制限はC++では削除されており、アドレスを取得することで変数がレジスタに格納されないようにすることができます。

最新のコンパイラの多くは、C++のregisterキーワードを無視しています(無効な方法で使用されている場合を除きます)。彼らは、registerキーワードが有用であったときよりも、最適化するほうがはるかに優れています。私はニッチターゲットプラットフォームのコンパイラがより真剣にそれを扱うことを期待しています。

+1

いつも**の**ローカル変数を 'register'でマークしたコードを見るのは驚きました。 –

+3

@PeteBecker誰がRAMを必要としますか?私はすべてのレジスタです! –

+0

あなたの議論はC++のみです。 Cはレジスタ変数に制限を課す。 –

3

これはコンパイラのヒントです。あなたはそれをレジスタに配置することはできません。いずれにしても、コンパイラーライターは、おそらくアプリケーションプログラマーよりもターゲットアーキテクチャーに関する知識が優れているため、レジスター割り振りの決定を行うコードを書く方が適しています。言い換えれば、registerを使用して何かを達成する可能性は低いです。

+0

あなたの議論はC++のみです。 Cはレジスタ変数に制限を課す。 –

3

一般的には不可能です。具体的には、確率を上げるための対策をとることができます。

適切な最適化レベルを使用してください。 -O2

は、レジスタ変数のアドレスを取得しないでください

register int a,b,c,d,e,f,g,h,i, ... z; // can also produce an error 
// results in _spilling_ a register to stack 
// as the CPU runs out of physical registers 

小さな変数の数にしてください。

register int a; 
int *b = &a; /* this would be an error in most compilers, but 
       especially in the embedded world the compilers 
       release the restrictions */ 

いくつかのコンパイラでは、提案することができ

register int a asm ("eax"); // to put a variable to a specific register 
+0

あなたの議論はC++のみです。 Cは 'register'変数に制限を課します。また、 'asm'に関するgccのあなたの例は誤解を招きます。 gccの場合、これは「提案」ではありません。レジスタを指定すると、そのレジスタが存在し、*が使用されます。 –

1

キーワードは、コンパイラがRAMの2メガバイトを持つマシンで合わせていた時間の残りは(と18台の端末間で共有されている「登録」ユーザーはそれぞれにログインしています)。または128-256KBのRAMを備えたPC /家庭用コンピュータ。その時点で、コンパイラはどのレジスタをどの変数に使用するかを決める大きな関数を実際には実行できず、レジスタを最も効果的に使用することができませんでした。したがって、プログラマがregisterで "ヒント"を与えた場合、コンパイラはそれをレジスタに入れます(可能であれば)。

現代のコンパイラは、2MBのRAMに数回は収まらないが、レジスタに変数を割り当てることははるかに巧妙である。与えられた例では、コンパイラがそれをレジスタに入れないことは非常にうまくありません。明らかに、レジスタの数は限られており、十分に複雑なコードが与えられていると、いくつかの変数はレジスタに収まらないことになります。しかし、このような単純な例の場合、現代のコンパイラはiをレジスタにします。おそらく、ostream& ostream::operator<<(ostream& os, int x)のどこかになるまでメモリに触れません。

+0

ハハ、2MBの18端末。私の芝生から降りてください。[CP-67は60人のユーザーをサポートしていました](http://www.leeandmelindavarian.com/Melinda/25paper.pdf)[半分](http://bitsavers.trailing-edge.com /pdf/ibm/360/funcChar/GA27-2719-2_360-67_funcChar.pdf)。 – jthill

+0

私の学校では、RSTS-Eを実行している2MBのPDP-11を共有していました。私の学校には8台の端末と1台のプリンタがあり、次の学校では8台あり、 (プラスいくつかの他の場所に散在しているいくつかのランダムな端子)。そしてそのためのCコンパイラがありましたが、私たちの大部分は当時の現代の言語、Pascalを使用していました。 –

5

registerキーワードは、CおよびC++で異なる意味を持ちます。 C++では、実際には冗長性があり、現在は廃止されているようです。

Cでは異なります。最初にキーワードの名前を文字通り取らないでください。現代のCPU上の「ハードウェアレジスタ」とは必ずしも一致しません。 register変数に課されている制限は、アドレスを取得できないということです。&操作は許可されていません。これにより、最適化のための変数をマークし、そのアドレスを取ろうとするとコンパイラがあなたに叫ぶようにすることができます。特にregister変数もconstであることは決してエイリアスではないため、最適化の候補になります。

Cのようにregisterを使用すると、変数のアドレスを取得する場所を体系的に考える必要があります。これはおそらく、オブジェクトやそのようなものへの参照に大きく依存しているC++では望んでいないでしょう。これは、C++がregister変数のこのプロパティをCからコピーしなかった理由です。

+0

私は、第2段落の最初の文で "冗長"の代わりに "文字通り"(または "逐語的")を意味すると思います。 – Jeff

0

唯一の方法は、インラインアセンブリを使用することです。しかし、これを行っても、コンパイラが値をインラインアセンブリブロックのの外側に格納しないことは保証されません。もちろん、あなたのOSはあなたのプログラムをいつでも中断し、あなたのすべてのレジスタをメモリに保存して、CPUに別のプロセスを任せることができます。

したがって、すべての割り込みを無効にしてアセンブラコードをカーネル内に書き込まない限り、変数が決してメモリに到達しないようにする方法は絶対にありません。

もちろん、安全性に懸念がある場合にのみ該当します。パフォーマンスの観点からは、通常は-O3でコンパイルするだけで十分ですが、コンパイラは通常、どの変数をレジスタに保持するかを決めるのにかなり良い仕事をします。とにかく、レジスタに変数を格納することは、パフォーマンスチューニングの小さな側面の1つに過ぎません。さらに重要な点は、余計な作業や高価な作業が内部ループで行われないようにすることです。

0

volatile register int i = 10をC++で使用すると、iを確実に登録することができます。 volatileキーワードは、コンパイラが変数iを最適化することを許可しません。

1

一般に、CPPコンパイラ(g ++)はコードに対してかなりの最適化を行います。したがって、レジスタ変数を宣言するとき、コンパイラがその値をレジスタに直接格納する必要はありません。 (つまり)コード 'register int x'はコンパイラがそのintをレジスタに直接格納することにはなりません。しかし、コンパイラに強制することができれば、成功する可能性があります。

たとえば、次のコードを使用すると、コンパイラは自分の望むことを強制することがあります。次のコードのコンパイルでエラーが発生する可能性があります。これは、intが実際にレジスタに直接格納されていることを示します。

int main() { 
    volatile register int x asm ("eax"); 
    int y = *(&x); 
    return 0; 
} 

私の場合、g ++コンパイラはこの場合、次のエラーを投げています。

[[email protected] cpp]$ g++ register_vars.cpp 
register_vars.cpp: In function ‘int main()’: 
register_vars.cpp:3: error: address of explicit register variable ‘x’ requested 

ライン「揮発性レジスタint型のx ASM( 『EAX』)は、」「EAX」に整数xを格納し、コンパイラに指示されて登録し、そうすることで任意の最適化を行いません。これは、値がレジスタに直接格納されることを確認します。そのため、変数のアドレスにアクセスするとエラーが発生します。

また、Cコンパイラ(gcc)は、次のコード自体でエラーになることがあります。

int main() { 
    register int a=10; 
    int c = *(&a); 
    return 0; 
} 

私の場合、gccコンパイラはこの場合、次のエラーを投げています。

[[email protected] cpp]$ gcc register.c 
register.c: In function ‘main’: 
register.c:5: error: address of register variable ‘a’ requested 
+0

この 'asm(" eax ")'構文はまさに私が探していたものです。実際に質問に答えてくれてありがとう – portforwardpodcast

関連する問題