Attribute
简介
目前市面上大多数的C/C++集成开发环境(IDE)使用的编译工具链主要是GCC、Clang、ARMCC、IAR Embedded Workbench。为了使用一些高级编译器特性,我们需要了解一些编译器指令,比如GNU C的__attribute__
,这种指令在uboot和Linux源代码中经常被使用。
in GNUC or Clang
__Attribute__
是 GNU C 的一大特色,其可以向编译器声明以下属性:
- 函数属性(Function Attribute)
- 变量属性(Variable Attribute)
- 类型属性(Type Attribute)
函数属性可以帮助开发人员在函数声明中添加一些特性,这可以使编译器在错误检查方面增强。 变量属性允许对变量或结构体成员使用特定的属性进行修饰,例如结构体的对齐控制。
Clang 也借用了GCC的__attribute__,并进行了扩展。
语法格式:__attribute__ ((attribute-list))
。attribute的前面和后面都有两个底线,后面紧跟着两对元括号, attribute-list是一个用逗号分隔开的属性清单。
**位置约束:**放于声明的尾部 “;” 之前。
函数属性(Function Attribute)
常用属性
packed
让编译器在编译时取消结构体的字节优化对齐,并依照实际占用的字节数进行对齐。 在某些场景用户不希望编译器对字节对齐进行调整,否则处理起来会比较麻烦,那么可以使用该属性。
例如在源代码中定义了两个结构体
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)); // 4
printf("%d", sizeof(strpkd)); // 3
}
aligned
规定变量或结构体成员最小对齐格式,以字节为单位。 让用户自行决定变量的对齐字节数,例如一些处理器架构要求向量表需要按照规定的对齐地址放置,这时用户就需要进行控制了
在代码中定义了一个32位变量 :
uint32_t var_in_8bytes __attribute__((aligned(8)));
查看链接后的map映射文件,可以验证对齐的字节数和地址。
同样,你也可以使用预设的对齐方式。 如果aligned后面不紧跟着一个指定的数字值,那么编译器将依据你的目标机器状况使用最大、最有益的对齐方式。
struct mystr
{
int16_t a[3];
} __attribute__ ((aligned));
section
section 控制变量或函数编译后所在的段名。 在嵌入式软件开发时使用的非常多,例如有外扩Flash或RAM时,需要将变量或函数放置到外扩储存空间,可以在连结脚本中指定段名来操作。 在使用MPU(储存保护)的MCU编程时,需要对存储器划分区域,将变量或代码放置到对应的区域,通常也是通过段操作来实现。
const int identifier[3] __attribute__ ((section ("ident"))) = { 1,2,3 };
void myfunction (void) __attribute__ ((section ("ext_function")))
上述代码分别在编译后,数组和函数所在的段分别为indent
和ext_function
。
段定义相关可以去看[链接文件的讲解](GCC 链接脚本.md)
unused
unused 告诉编译器,如果修饰的函数或变量在程序中没有使用,编译时不提出 unused 警告
-
未使用的函数参数
void example_function(int used_param, int unused_param __attribute__((unused))) { // 仅使用 used_param printf("Used parameter: %d\n", used_param); }
-
未使用的变量
int global_variable __attribute__((unused)); // 未使用全局变量 void example_function() { int used_variable = 10; int unused_variable __attribute__((unused)) = 20; // 未使用局部变量 printf("Used variable: %d\n", used_variable); }
-
未使用的函数
static void unused_function() __attribute__((unused)); // 只能在声明处加 unused static void unused_function() { // 函数体 } int main() { // 未调用 unused_function return 0; }
used
此属性附加到具有静态储存的变量,表示即使变量看起来没有被引用,也必须保留该变数。 否则在链接的时候链接器发现某个变量未被引用,会将此变量优化掉。