GNU C __attribute__機制

GNU C __attribute__機制

attribute 的語法格式

attribute ((attribute-list))

attribute的前面和後面都有兩個下劃線,後面緊跟兩對元括弧, attribute-list是一個用逗號分隔開的屬性列表。attribute ((attribute-list))放於聲明的尾部「;」之前。

常用屬性

packed

讓編譯器在編譯時取消結構體的字節優化對齊,按照實際佔用的字節數進行對齊。

  • pack可以壓縮變量所佔內存的空間。
  • pack作用於結構體或類的定義。
  • pack的作用是改變結構體或類中成員變量的布局規則。
  • 若某一個結構體的默認pack為n,pack指定的對齊規則m大於n,則該pack忽略。
  • pack指定規則時必須為2的n次冪。

例如在源碼中定義了兩個結構

 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

section控制變量或函數在編譯時的段名。在嵌入式軟體開發時用的非常多,比如有外擴Flash或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

若兩個或兩個以上全局符號名字一樣,而其中之一聲明為weak symbol(弱符號),則這些全局符號不會引發重定義錯誤。當普通符號存在時,連結器會忽略掉弱符號,如果不存在普通符號,則使用弱符號。 可以實現類似重載,回調之類的功能。

记录并分享
Built with Hugo
Theme Stack designed by Jimmy