10

以下のコードでは、

int main( )
{
    register int arr[4];
    /* ... */
}

「arr」が一部のCPUレジスタに割り当てられている可能性はありますか? (CPUに4つ以上のレジスタがあると考えてください)。

または、コンパイラは配列のレジスタストレージ クラスを無視します。

4

5 に答える 5

11

私の理解では、答えはYESNOです。

いいえ、なぜなら、

  1. どの配列要素も明示的にアドレス可能でなければなりません (つまり、たとえば 16 ビット uC/uP の場合、そのアドレスは常に 0x0000 から 0xFFFF アドレス空間の間にある必要があります)。

  2. CPU レジスタは、レジスタ ダイレクトアドレッシング モード ( mov r2,#100など) を使用してアクセスされます。このアドレッシング モードには有効なアドレスがありません。(アドレッシングモードとは見なされません)

  3. 配列要素は、連続したメモリ位置に存在する必要があります。(ポインター演算の場合、配列を使用する主な理由)

はい、なぜなら、

  1. コンパイラは上記の配列にレジスタを割り当てることができるため、いくつかの制限された操作を実行できます。ただし、最適化のためにアドレスを内部的に使用する操作は使用できません。

以下のコードを参照してください。

int main( )
{
  register int arr[4];
  int i;

  arr[0] = 10;      /* OK */
  arr[1] = 20;      /* OK */
  arr[2] = 30;      /* OK */
  arr[3] = 40;      /* OK */

  for(i=0;i<4;i++)
    arr[i]=10;    /* Error : "address of register variable 'arr' requested" */

  return 0;
}

したがって、私の最終的な結論は、理想的には、コンパイラーが許可していても、レジスター・ストレージ・クラスを配列で使用してはならないということです。

私を修正するか、さらに入力してください。:-)

于 2013-06-27T12:14:47.417 に答える
5

C89 標準では、レジスタ ストレージ クラスの変数に対するアドレスの取得や同様の操作は許可されていません (少なくとも、私が持っているドラフトでは許可されていません: 3.5.1、注 49 を参照)。そのような配列には sizeof 演算子のみが有効であるとさえ述べています。C99 標準は 6.7.1 の register ストレージ クラスを参照しており、ここでメモ 103 は C89 ドラフトとまったく同じことを宣言しています。

結論として、レジスタ ストレージ クラスと配列を混在させるべきではありません。宣言自体は有効ですが、技術的には役に立ちません。

それ以外の場合は、一般的に疑問がある場合は、分解リストを確認してください。8 ビット コントローラを対象とする一部のコンパイラは、驚くべきことを行う場合があります。

于 2013-07-02T17:29:26.967 に答える
1

最適化コンパイラは、おそらくこれらの配列要素のいずれかを CPU レジスタに一時的に割り当て、そこで操作を実行します。

しかし、その配列をレジスタに強制することが可能かどうかを尋ねている場合、これを行う方法がわかりません。単一の変数 (gcc 内) の場合、「明示的な登録変数」を使用できます ( http://gcc.gnu.org/onlinedocs/gcc/Explicit-Reg-Vars.htmlを参照)。

于 2013-06-27T13:45:08.103 に答える