ARM 编译器关键字与属性详解
在 ARM 编译器中,关键字和属性的使用对内存对齐、函数优化、内联汇编等方面的性能和功能优化起到了至关重要的作用。本文将对关键的编译器指令、属性以及它们的具体应用进行详细说明。
一. 关键字和运算符
1. __align(n)
:内存对齐
该关键字用于指示编译器将变量按 n
字节边界对齐。
- 局部变量:
n
值可为 1、2、4 或 8。 - 全局变量:
n
可以为 2 的次幂,最大值为0x80000000
。
注意事项:
只能向更高对齐进行对齐,如可以将 2 字节对象按 4 字节对齐,但不能将 4 字节对象按 2 字节对齐。
用法示例:
__align(8) char buffer[128]; // buffer 从 8 字节对齐边界开始
void foo(void) {
__align(16) int i; // 不允许对局部变量使用 16 字节对齐
}
__align(16) int i; // 作为全局变量,16 字节对齐被允许
2. __asm
:内联汇编
用于将编译器指令传递到 ARM 汇编器 armasm 中。
用法示例:
// 嵌入式汇编函数声明
__asm void my_strcpy(const char *src, char *dst);
// 内联汇编示例
int qadd(int i, int j) {
int res;
__asm {
QADD res, i, j
}
return res;
}
// 使用汇编标签
int count __asm__("count_v1"); // 输出 count_v1 而非 count
3. __forceinline
:强制内联
强制编译器将指定函数内联,类似于 C++ 中的 inline
,但如果遇到递归等情况可能不会执行。
用法示例:
__forceinline static int max(int x, int y) {
return x > y ? x : y; // 尽可能进行内联
}
4. __inline
:提示内联
与 __forceinline
类似,但只是建议编译器尽量内联。
用法示例:
__inline int f(int x) {
return x * 5 + 1;
}
5. __packed
:压缩内存布局
用于设置结构体或联合体的对齐为 1 字节,从而节省空间,但可能影响性能。
用法示例:
typedef __packed struct {
char x;
int y;
} X; // 结构体大小为 5 字节
二. 函数属性
1. __attribute__((always_inline))
:强制内联
与 __forceinline
功能相同,确保函数总是被内联。
用法示例:
static int max(int x, int y) __attribute__((always_inline)) {
return x > y ? x : y;
}
2. __attribute__((used))
:防止优化移除
强制保留函数,即使未引用。
用法示例:
static int keep_this(int x) __attribute__((used));
3. __attribute__((unused))
:避免未使用警告
告知编译器不会使用某些变量或函数,避免生成警告。
三. 变量属性
1. __attribute__((at(address)))
:指定绝对地址
可以指定变量存储在特定的内存地址。
用法示例:
const int x1 __attribute__((at(0x10000))) = 10; // 只读变量
int x2 __attribute__((at(0x12000))) = 10; // 读写变量
2. __attribute__((zero_init))
:零初始化
指示编译器不为变量进行零初始化,适用于未赋初值的变量。
四. 内联指令函数
1. __breakpoint
:插入断点
允许在代码中插入断点指令,适用于调试。
用法示例:
void func(void) {
__breakpoint(0xF02C);
}
2. __nop
:空指令
用于插入一个空操作指令。
用法示例:
void __nop(void);
通过使用上述关键字和属性,可以对编译器行为进行精确控制,优化代码性能和内存布局。