下面的程序编译没有错误。
#include <stdio.h>
char addr_a[8];
char addr_b[8];
unsigned long my_addr = (unsigned long)addr_b - 8; // PASS
// unsigned long my_addr = (unsigned long)addr_b - (unsigned long)addr_a; // FAIL (error: initializer element is not constant)
int main() {
printf("%lx\n", my_addr);
return 0;
}
有趣unsigned long my_addr = (unsigned long)addr_b - (unsigned long)addr_a
的是,当我设置编译器时抛出“错误:初始化元素不是常量”。
我知道全局变量只能用常量表达式初始化。我也知道可以在全局初始化器中使用的常量表达式的类型在C 标准的第 6.6p7 节中指定:
初始化器中的常量表达式允许更大的自由度。这样的常量表达式应为或评估为以下之一:
- 算术常数表达式,
- 一个空指针常量,
- 地址常量,或
- 完整对象类型的地址常量加上或减去整数常量表达式。
请注意,允许使用地址常量减去整数常量,但不允许使用地址常量减去另一个地址常量。
问题:
为什么 C 标准会限制初始化全局变量的方式?是什么阻止了 C 标准的接受unsigned long my_addr = (unsigned long)addr_b - (unsigned long)addr_a
?
你为什么要这个?
假设addr_a
并分别addr_b
表示该.text
部分的开始和结束。程序可能想要映射.text
具有 size 的部分(unsigned long)addr_b - (unsigned long)addr_a
。trust-firmware-a项目在 Boot Loader 阶段 2 (BL2) 中执行此操作。请参阅BL_CODE_END - BL_CODE_BASE
,它在arm_bl2_setup.c中使用。