[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.29 変数の属性の指定

キーワード __attribute__ を使うと、変数や構造体のフィールドの 特別な属性を指定することができる。このキーワードの後ろに 属性の指定を二重括弧の中に入れて書く。現在、変数用には 8 個の 属性が定義されている。alignedmodenocommonpackedsectiontransparent_unionunusedweak である。その他に、 関数(see section 関数属性の宣言) と型(see section 型の属性の指定) で 使える属性がある。

また、各キーワードの前後に ‘__’ を付けた属性を指定しても良い。 これにより、同じ名前のマクロがある可能性を心配することなく、 ヘッダファイルの中でこれらの属性を使うことができる。 例えば、aligned の代わりに __aligned__ を使うことができる。

aligned (alignment)

この属性は変数や構造体のフィールドの最小のアラインメントをバイト単位で 指定する。例えば、

 
int x __attribute__ ((aligned (16))) = 0;

と宣言すると、GCC はグローバル変数 x を 16 バイト境界に 割り当てる。68040 では、これをasm 式と組み合わせることで、 オペランドが16バイト境界に整列している必要がある move16 命令を 使えるようになる。

また、構造体のフィールドのアラインメントを指定することもできる。 例えば、倍語境界に整列した int の対を作るには以下のように 書けば良い。

 
struct foo { int x[2] __attribute__ ((aligned (8))); };

これは、double 型のメンバを入れた共用体を作って、 その共用体を倍語境界に整列させるという通常の手段の代替方法である。

関数に対してはアラインメントを指定することはできない。 関数のアラインメントは機種によって決まっており、変更不可能である。 typedef 名に対してもアラインメントを指定することはできない。 typedef 名は新たな型ではなくて、単なる別名に過ぎないからである。

上の例のように、与えられた変数や構造体フィールドに対して GCC に 使って欲しいと思うアラインメントを明示的に指定することが可能である。 もう一つの方法として、アラインメント因子を書かずに、コンパイルの ターゲット機種の意味のある最大のアラインメントを変数やフィールドに 与えるようコンパイラに任せることもできる。 例えば、以下のように書くことができる。

 
short array[3] __attribute__ ((aligned));

aligned 属性の指定で、アラインメント因子を書かないと、GCC は、 宣言された変数やフィールドに、読者のコンパイルのターゲットである機種で 任意のデータ型に対して使われる最大のアラインメントを 自動的に設定する。こうすると、コピー操作の効率が良くなることが多い。 GCC は、このようにアラインメントを設定した変数やフィールドとの 間のコピーを行うときに、最大のメモリの塊をコピーする命令を 使うことができるからである。

aligned 属性ができるのはアラインメントを大きくすることだけである。 だが、小さくするには packed 属性を指定すれば良い。

aligned 属性の効果は、リンカの持つ制限により制限を 受ける可能性があることに注意して欲しい。多くのシステムでは、 リンカは、変数のアラインメントを、ある決まった最大のアラインメントまでしか 調整できない。(リンカの中には、可能なアラインメントの最大値が 非常に小さいものがある。) 読者のところのリンカが、変数を最大で 8 バイト境界にまでしか 整列できないのであれば、__attribute__aligned(16) と 指定しても、8 バイトのアラインメントしか提供されない。 詳細な情報についてはリンカのドキュメントを見て欲しい。

mode (mode)

この属性は、宣言に対するデータ型を指定する。この型はモード mode に対応するどんな型でも良い。これは実質的には、 その幅に対応した整数型か浮動小数点型を要求したことになる。

また、モード ‘byte’ または ‘__byte__’ を指定して、 一バイト整数に対応するモードであることを指示することもできる。 同様に、‘word’ または ‘__word__’ で一語長の整数モードを、 ‘pointer’ または ‘__pointer__’ でポインタを表現するのに 使われるモードを指示する。

nocommon

この属性は、GNU CC に対し、変数をコモン領域に置かずに、直接 メモリ割当を行なうよう要求する。オプション ‘-fno-common’ オプションを 指定すると、全ての変数に対しこれを行なう。

変数に対し nocommon 属性を指定すると、ゼロによる初期化が 行なわれることになる。ある変数は、一個のソースファイルでしか初期化 してはならない。

packed

packed 属性は、変数や構造体フィールドが持つアラインメントを 最小限にすべきであることを指定する。最小限のアラインメントとは、 aligned 属性でもっと大きな値を指定しない限り、変数の場合は 1バイトであり、構造体フィールドの場合は 1 ビットである。

以下の構造体では、フィールド x がパックされており、 このため a の直後に配置される。

 
struct foo
{
  char a;
  int x[2] __attribute__ ((packed));
};
section ("section-name")

通常、GNU CC は生成したオブジェクトを databss と いったセクションに置く。だが、追加で別のセクションが必要になったり、 あるいはある種の特別な変数を特別なセクションに置く必要があったりすることが ある。これは、例えば特別なハードウェアにマップするため等の理由で必要になる。 section 属性は、変数(または関数)をある特定のセクションに置くことを 指定する。例えば、以下のプログラムでは色々な固有のセクション名を 使っている。

 
struct duart a __attribute__ ((section ("DUART_A"))) = { 0 };
struct duart b __attribute__ ((section ("DUART_B"))) = { 0 };
char stack[10000] __attribute__ ((section ("STACK"))) = { 0 };
int init_data __attribute__ ((section ("INITDATA"))) = 0;

main()
{
  /* Initialize stack pointer */
  init_sp (stack + sizeof (stack));

  /* Initialize initialized data */
  memcpy (&init_data, &data, &edata - &data);

  /* Turn on the serial ports */
  init_duart (&a);
  init_duart (&b);
}

section 属性は、上記の例のように、グローバル変数の 初期値付き定義に使うこと。GNU CC は、初期値なしの変数宣言に section 属性を使うと、警告を発するか、さもなければ無視する。

section 属性は、リンカの動作する仕組みにより、 完全に初期化されたグローバルな定義にしか使うことができない。 リンカは各オブジェクトは一回だけ定義されることを要求する。 例外は、非初期化変数であり、一時的に common (あるいは bss) セクションに置かれ、このため複数回「定義」可能である。 変数を強制的に初期化するには、‘-fno-common’ オプションか nocommon 属性を使うことが出来る。

オブジェクトファイル形式の中には、任意のセクションをサポートしないものが あり、そのため section 属性は全てのプラットフォームで利用できる わけではない。あるモジュールの全内容をある特定のセクションに対応 させる必要がある場合は、代わりにリンカの機能を使うことを考えたほうが良い。

transparent_union

この属性は、共用体である関数の仮引数に付け、対応する実引数の型は その共用体のどのメンバの型であっても良いが、実引数は共用体の 先頭のメンバの型として渡されるということを意味する。 詳細は See section 型の属性の指定 を参照。また、この属性を共用体データ型の typedef に使うこともできる。その場合、この型を持つ全ての 関数仮引数に適用される。

unused

この属性は、変数に付け、この変数が使用されない可能性があることを意味する。 GNU CC は、この変数については警告を出さない。

weak

weak 属性は、See section 関数属性の宣言 で説明する。

model (model-name)

M32R/D ではこの属性を使って、あるオブジェクトのアドレス可能性を 設定する。識別子 model-name は、smallmediumlarge の一つで、それぞれコードモデルを表す。

small モデルのオブジェクトはメモリの下位 16MB に置かれる (これにより、これらのオブジェクトのアドレスは ld24 命令で ロード可能である。)

medium モデルと large モデルのオブジェクトは 32 ビットのアドレス空間の どこにでも置かれる(GNU CC はこれらのアドレスをロードするために、 seth/add3 命令を生成する)。

複数の属性を指定するには、それらを二重括弧で囲み、その中でカンマで 各属性を区切る。例えば、‘__attribute__ ((aligned (16), packed))’ とする。


This document was generated using texi2html 1.78.