GNU C __attribute__ メカニズム

GNU C __attribute__ メカニズム

attribute の構文形式

attribute ((attribute-list))

属性の前後には 2 つのアンダースコアが続き、その後に 2 組のメタ括弧が続きます。 attribute-list は、属性のカンマ区切りのリストです。 attribute ((attribute-list)) は「;」の前に配置されます。宣言の最後に。

共通のプロパティ

packed

コンパイラがコンパイル中に構造体のバイト最適化アライメントをキャンセルし、実際に占有されているバイト数に応じてアライメントします。

  • Pack は変数が占めるメモリ空間を圧縮できます。
  • パックは構造体またはクラス定義に基づいて動作します。
  • Pack の機能は、構造体またはクラス内のメンバー変数の配置規則を変更することです。
  • 特定の構造体のデフォルトのパックが n で、パックで指定された整列規則 m が n より大きい場合、そのパックは無視されます。
  • ルールを指定する場合、パックは 2 の n 乗である必要があります。

たとえば、ソース コードで 2 つの構造が定義されているとします。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
struct unpacked_str
{
  uint8_t x;
  uint16_t y;
};

struct packed_str
{
  uint8_t x;
  uint16_t y;
}__attribute__ ((packed));

struct unpacked_str strupkd;
struct packed_str strpkd;

int main(void)
{
  printf("%d", sizeof(strupkd));
  printf("%d", sizeof(strpkd));
}

Clang を使用してコンパイルすると、実行時の出力はそれぞれ 4 と 3 になります。

aligned

変数または構造体メンバーの最小アライメント形式をバイト単位で指定します。変数を何バイト配置するかをユーザーが決定できるようにします。

1
2
3
4
aligned既可以作用于结构体或类的定义,也可以作用于变量的声明。
aligned只是建议编译器对指定变量或指定类型的变量分配内存时的规则。
若某一个结构体的默认pack为n,若aligned指定的对齐规则s大于n,则此时结构体的大小一定为s的整数倍。
aligned指定规则时都必须为2的n次幂。
  • aligned が変数に作用する場合、その機能は、変数にメモリを割り当てるときに、その変数に指定されたメモリに割り当てる必要があることをコンパイラに指示することです。変数を操作しても、変数のサイズは変わりません。

32 ビット変数はコードで定義されています。

1
uint32_t var_in_8bytes __attribute__((aligned(8)));

変数 var_in_8bytes のメモリ開始アドレスは 8 の倍数です。

  • aligned が型に作用する場合、その役割は、その型で宣言されたすべての変数が指定されたアライメントでメモリに割り当てられる必要があることをコンパイラに伝えることです。この属性が構造体の宣言に適用されると、構造体のサイズが変更される可能性があります。
1
2
3
4
5
6
7
8
struct Test{
  char a[3];
} __attribute__((aligned(8)));

int main() {
  //8
  std::cout << sizeof(Test);
}

上に示したように、align が構造定義に適用されると、構造のサイズが変更されます。構造体の最終的なサイズは、aligned で指定されたサイズの整数倍になります。

section

セクションは、コンパイル時に変数または関数のセクション名を制御します。組み込みソフトウェア開発で広く使用されています。たとえば、外部フラッシュまたは RAM がある場合、変数または関数を外部ストレージ領域に配置する必要があります。リンクスクリプトにセグメント名を指定して動作させることができます。 MPUを使用してMCUをプログラミングする場合(メモリ保護)、メモリを領域に分割し、対応する領域に変数やコードを配置する必要があります。これは通常、セグメント操作によって実現されます。

1
2
const int identifier[3] __attribute__ ((section ("ident"))) = { 1,2,3 };
void myfunction (void) __attribute__ ((section ("ext_function")))

上記のコードをコンパイルすると、配列と関数が配置されるセクションはそれぞれ「indent」と「ext_function」になります。

unused

これは、関数または変数が使用されない可能性が高く、コンパイラーはこの関数に対して警告を生成しないことを意味します。これは、関数の実装で使用されないパラメーターで宣言できます。次に例を示します。

1
int main(int argc __attribute__((unused)), char **argv)

used

この属性は、静的ストレージを持つ変数に付加されます。つまり、参照されていないように見える場合でも変数を保持する必要があります。それ以外の場合、リンク時にリンカは変数が参照されていないことを検出し、変数を最適化します。

weak

2 つ以上のグローバル シンボルが同じ名前であり、そのうちの 1 つが弱いシンボルとして宣言されている場合、これらのグローバル シンボルは再定義エラーを引き起こしません。通常のシンボルが存在する場合、リンカは弱いシンボルを無視します。通常のシンボルが存在しない場合は、弱いシンボルが使用されます。オーバーロードやコールバックなどの関数を実装できます。

记录并分享
Hugo で構築されています。
テーマ StackJimmy によって設計されています。