絶対アドレスへのデータ配置
@演算子または#pragma locationディレクティブを使用して、グローバル変数や静的変数を絶対アドレスに配置できます。
変数を絶対アドレスに配置するには、@ (演算子)演算子や#pragma locationディレクティブの引数に、実際のアドレスを示す定数を指定します。配置する変数のアライメント条件を満たしている絶対アドレスを指定する必要があります。
注記
絶対アドレスに配置される__no_init変数のすべての宣言は、仮定義です。仮定義の変数は、コンパイルするモジュールで必要な場合に、コンパイラからの出力にのみ保持されます。こうした変数は、使用されるすべてのモジュールで定義され、同じ方法で定義されている限りは機能します。こうした宣言は、変数を使用する全モジュールにインクルードされるすべてのヘッダファイルに配置することをお勧めします。
絶対アドレスに配置される他の変数は、通常の宣言と定義の区別を使用します。こうした変数については、1つのモジュール(通常はイニシャライザ)でのみ定義を提供する必要があります。他のモジュールは、明示的アドレスの有無に関わらず、extern宣言を使用すれば変数を参照できます。
例
この例では、__no_initで宣言した変数が絶対アドレスに配置されます。これは、複数のプロセス、アプリケーションなどの間でインタフェースする場合に便利です。
__no_init volatile char alpha @ 0xFF2000; /* OK */次の例では、2つのconst宣言オブジェクトが含まれます。1つは初期化されず、もう1つは特定の値に初期化されます。(最初のケースでは、外部インタフェースからアクセス可能な構成パラメータに便利です。) 両方のオブジェクトはROMに配置されます。2番目においては、値が既知であるため、必ずコンパイラが変数から実際に読み出すとは限りません。
#pragma location=0xFF2004 __no_init const int beta; /* OK */ const int gamma @ 0xFF2004 = 3; /* OK */
1番目においては、値はコンパイラで初期化されません。別の方法で値を設定する必要があります。代表的な用途は、値が別々にROMにロードされる構成や、リードオンリーの特殊機能レジスタです。
以下の例には、間違った使用法を示します。
__no_init int epsilon @ 0xFF2007; /* Error, misaligned. */C++についての注意
C++では、モジュールスコープのconst変数は静的(モジュールローカル)ですが、Cではこれらはグローバルです。つまり、特定のconst変数を宣言する各モジュールには、この名前で別の変数が含まれるということです。このようなモジュールの複数とアプリケーションをリンクする場合において、これらのモジュールがすべて、たとえば以下の宣言を(ヘッダファイル経由で)含む場合:
const __no_init int x @ 0x100; /* Bad in C++ */
リンカは、複数の変数がアドレス0x100に配置されていることを報告します。
この問題を回避し、プロセスをCとC++で同じにするには、以下の例のように、これらの変数をexternとして宣言します。
/* The extern keyword makes x public. */ extern const __no_init int x @ 0x100;
volatile指定された内容には内部リンケージが付与されないことに注意してください。そのため、変数がconst volatileで宣言されていた場合、externで宣言する必要はありませんでした。