轉載自https://blog.csdn.net/qlexcel/article/details/92656797
GNU C 的一大特色就是__attribute__ 機制。__attribute__ 可以設置函數屬性(Function Attribute )、變量屬性(Variable Attribute )和類型屬性(Type Attribute )。
__attribute__ 書寫特征是:__attribute__ 前后都有兩個下划線,並切后面會緊跟一對原括弧,括弧里面是相應的__attribute__ 參數。
__attribute__ 語法格式為:__attribute__ ((attribute-list))
關鍵字__attribute__ 也可以對結構體(struct )或共用體(union )進行屬性設置。大致有六個參數值可以被設定,即:aligned, packed, transparent_union, unused, deprecated 和 may_alias 。
在使用__attribute__ 參數時,你也可以在參數的前后都加上“__” (兩個下划線),例如,使用__aligned__而不是aligned ,這樣,你就可以在相應的頭文件里使用它而不用關心頭文件里是否有重名的宏定義。
二、__attribute__ 的參數介紹
1、aligned
指定對象的對齊格式(以字節為單位),如:
struct S {
short b[3];
} __attribute__ ((aligned (8)));
typedef int int32_t __attribute__ ((aligned (8)));
該聲明將強制編譯器確保(盡它所能)變量類 型為struct S 或者int32_t 的變量在分配空間時采用8字節對齊方式。
如上所述,你可以手動指定對齊的格式,同樣,你也可以使用默認的對齊方式。如果aligned 后面不緊跟一個指定的數字值,那么編譯器將依據你的目標機器情況使用最大最有益的對齊方式。例如:
struct S {
short b[3];
} __attribute__ ((aligned));
這里,如果sizeof (short )的大小為2byte,那么,S 的大小就為6 。取一個2 的次方值,使得該值大於等於6 ,則該值為8 ,所以編譯器將設置S 類型的對齊方式為8 字節。
aligned 屬性使被設置的對象占用更多的空間,相反的,使用packed 可以減小對象占用的空間。
需要注意的是,attribute 屬性的效力與你的連接器也有關,如果你的連接器最大只支持16 字節對齊,那么你此時定義32 字節對齊也是無濟於事的。
2、packed
使用該屬性對struct 或者union 類型進行定義,設定其類型的每一個變量的內存約束。就是告訴編譯器取消結構在編譯過程中的優化對齊(使用1字節對齊),按照實際占用字節數進行對齊,是GCC特有的語法。這個功能是跟操作系統沒關系,跟編譯器有關,gcc編譯器不是緊湊模式的,我在windows下,用vc的編譯器也不是緊湊的,用tc的編譯器就是緊湊的。
下面的例子中,packed_struct 類型的變量數組中的值將會緊緊的靠在一起,但內部的成員變量s 不會被“pack” ,如果希望內部的成員變量也被packed 的話,unpacked-struct 也需要使用packed 進行相應的約束。
struct unpacked_struct
{
char c;
int i;
};
struct packed_struct
{
char c;
int i;
struct unpacked_struct s;
}__attribute__ ((__packed__));
如:
在TC下:struct my{ char ch; int a;} sizeof(int)=2;sizeof(my)=3;(緊湊模式)
在GCC下:struct my{ char ch; int a;} sizeof(int)=4;sizeof(my)=8;(非緊湊模式)
在GCC下:struct my{ char ch; int a;}__attrubte__ ((packed)) sizeof(int)=4;sizeof(my)=5
下面的例子中使用__attribute__ 屬性定義了一些結構體及其變量,並給出了輸出結果和對結果的分析。代碼為:
struct p
{
int a;
char b;
short c;
}__attribute__((aligned(4))) pp;
struct m
{
char a;
int b;
short c;
}__attribute__((aligned(4))) mm;
struct o
{
int a;
char b;
short c;
}oo;
struct x
{
int a;
char b;
struct p px;
short c;
}__attribute__((aligned(8))) xx;
int main()
{
printf("sizeof(int)=%d,sizeof(short)=%d.sizeof(char)=%d\n",sizeof(int)
,sizeof(short),sizeof(char));
printf("pp=%d,mm=%d \n", sizeof(pp),sizeof(mm));
printf("oo=%d,xx=%d \n", sizeof(oo),sizeof(xx));
return 0;
}
輸出結果:
sizeof(int)=4,sizeof(short)=2.sizeof(char)=1
pp=8,mm=12
oo=8,xx=24
分析:都是字節對齊的原理,可以去看這兒:字節對齊
3、at
絕對定位,可以把變量或函數絕對定位到Flash中,或者定位到RAM。
1)、定位到flash中,一般用於固化的信息,如出廠設置的參數,上位機配置的參數,ID卡的ID號,flash標記等等
const u16 gFlashDefValue[512] __attribute__((at(0x0800F000))) = {0x1111,0x1111,0x1111,0x0111,0x0111,0x0111};//定位在flash中,其他flash補充為00
const u16 gflashdata__attribute__((at(0x0800F000))) = 0xFFFF;
2)、定位到RAM中,一般用於數據量比較大的緩存,如串口的接收緩存,再就是某個位置的特定變量
u8 USART2_RX_BUF[USART2_REC_LEN] __attribute__ ((at(0X20001000)));//接收緩沖,最大USART_REC_LEN個字節,起始地址為0X20001000.
注意:
1)、絕對定位不能在函數中定義,局部變量是定義在棧區的,棧區由MDK自動分配、釋放,不能定義為絕對地址,只能放在函數外定義。
2)、定義的長度不能超過棧或Flash的大小,否則,造成棧、Flash溢出。
4、section
提到section,就得說RO RI ZI了,在ARM編譯器編譯之后,代碼被划分為不同的段,RO Section(ReadOnly)中存放代碼段和常量,RW Section(ReadWrite)中存放可讀寫靜態變量和全局變量,ZI Section(ZeroInit)是存放在RW段中初始化為0的變量。
於是本文的大體意思就清晰了,__attribute__((section("section_name"))),其作用是將作用的函數或數據放入指定名為"section_name"對應的段中。
1)、編譯時為變量指定段:
__attribute__((section("name")))
RealView Compilation Tools for µVision Compiler Reference Guide Version 4.0
Home > Compiler-specific Features > Variable attributes > __attribute__((section("name")))
4.5.6. __attribute__((section("name")))
Normally, the ARM compiler places the objects it generates in sections like data and bss. However, you might require additional data sections or you might want a variable to appear in a special section, for example, to map to special hardware. The section attribute specifies that a variable must be placed in a particular data section. If you use the section attribute, read-only variables are placed in RO data sections, read-write variables are placed in RW data sections unless you use the zero_init attribute. In this case, the variable is placed in a ZI section.
Note
This variable attribute is a GNU compiler extension supported by the ARM compiler.
Example
/* in RO section */
const int descriptor[3] __attribute__ ((section ("descr"))) = { 1,2,3 };
/* in RW section */
long long rw[10] __attribute__ ((section ("RW")));
/* in ZI section *
long long altstack[10] __attribute__ ((section ("STACK"), zero_init));/
2)、編譯時為函數指定段
__attribute__((section("name")))
RealView Compilation Tools for µVision Compiler Reference Guide Version 4.0
Home > Compiler-specific Features > Function attributes > __attribute__((section("name")))
4.3.13. __attribute__((section("name")))
The section function attribute enables you to place code in different sections of the image.
Note
This function attribute is a GNU compiler extension that is supported by the ARM compiler.
Example
In the following example, Function_Attributes_section_0 is placed into the RO section new_section rather than .text.
void Function_Attributes_section_0 (void) __attribute__ ((section ("new_section")));
void Function_Attributes_section_0 (void)
{
static int aStatic =0;
aStatic++;
}
In the following example, section function attribute overrides the #pragma arm section setting.
#pragma arm section code="foo"
int f2()
{
return 1;
} // into the 'foo' area
__attribute__ ((section ("bar"))) int f3()
{
return 1;
} // into the 'bar' area
int f4()
{
return 1;
} // into the 'foo' area
#pragma arm section
5、多個屬性,組合使用
u8 FileAddr[100] __attribute__ ((section ("FILE_RAM"), zero_init,aligned(4)));
轉載自:
https://www.cnblogs.com/embedded-linux/p/5801999.html
https://blog.csdn.net/weixin_38233274/article/details/82188997