英文:
Does gcc cache the address of a global array at a static index by default?
问题
让我们假设我有全局数组
char global_array[3] = {33, 17, 6};
并且我访问 global_array[1]
。当gcc解释 global_array[1]
时,它会在运行时将1添加到 global_array
的地址,还是将 global_array[1]
更改为静态地址,假设使用 -O0 编译选项?如果不是这样,是否有一个编译器标志,可以让gcc将数组的静态索引转换为静态指针?
英文:
Let's say I have the global array
char global_array[3] = {33, 17, 6};
and I access global_array[1]
. When gcc interprets global_array[1]
, will it add 1 to the address of global_array
at runtime, or change global_array[1]
to a static address, assuming -O0? If not, is there a compiler flag to for gcc to make the static index of an array a static pointer?
答案1
得分: 0
当gcc解释global_array[1]时,假设使用-O0
,它会在运行时将1添加到global_array的地址,还是将global_array[1]更改为静态地址?
关于gcc在不同优化级别下的具体行为没有特定的保证。以x86_64的gcc 12.2为例,考虑以下代码:
int func (void)
{
char global_array[3] = {33, 17, 6};
return global_array[1];
}
在-O0
级别下,这将导致奇怪的汇编代码:
func:
push rbp
mov rbp, rsp
mov WORD PTR [rbp-3], 4385
mov BYTE PTR [rbp-1], 6
movzx eax, BYTE PTR [rbp-2]
movsx eax, al
pop rbp
ret
它将数组存储在堆栈上,但将神奇的数字4385作为一个字加载,然后在末尾加载6。那么4385是什么?它是0x1121的十六进制表示法。字节的值为0x11 = 17十进制和0x21 = 33,由于它是x86小端序,与数组的顺序相比,WORD
指令的字节顺序相反。
即使我使用了-O0
,这个字写入已经是某种形式的微优化。所以再次强调,不能提供保证。关于你的问题,访问部分rbp-2
确实类似于在运行时将1添加到地址。在这种情况下,它是从堆栈帧指针减去一个偏移量,但本质上是相同的操作(并且可能与将1添加到地址一样快/慢)。
当启用优化时,通常的做法是用绝对值替换整个操作。
如果不是这样,是否有编译器标志可以使数组的静态索引成为静态指针?
通过更改编译器选项可能不是实现这一目标的方法。如果你希望有一个指向固定地址的指针,通常的步骤是:
- 在特定目标的链接器脚本中创建一个自定义段位于固定地址。
- 在文件范围内声明你的数组,并使用gcc的变量属性将其分配到你的自定义段内。
- 现在
&global_array[1]
始终是相同的地址。
英文:
> When gcc interprets global_array[1], will it add 1 to the address of global_array at runtime, or change global_array[1] to a static address, assuming -O0
?
There's no particular guarantees of what gcc does and does not depending on level of optimization. Take your example under gcc 12.2 for x86_64:
int func (void)
{
char global_array[3] = {33, 17, 6};
return global_array[1];
}
This results in peculiar assembly code under -O0
:
func:
push rbp
mov rbp, rsp
mov WORD PTR [rbp-3], 4385
mov BYTE PTR [rbp-1], 6
movzx eax, BYTE PTR [rbp-2]
movsx eax, al
pop rbp
ret
It is storing the array of the stack but it loads the magic number 4385 as a word, then loads a 6 at the end. Now wth is 4385? It is 0x1121 hex. Where the bytes have values 0x11 = 17dec and 0x21 = 33, and since it is a x86 little endian, the byte order for the WORD
instruction is reversed vs the order of the array.
This word write is already some manner of mini-optimization even though I used -O0
. So again - no guarantees. Regarding your question, the access part rbp-2
is indeed similar to adding 1 the to the address in runtime. In this case it is subtracting an offset from the stack frame pointer, but that's essentially the same thing (and likely as fast/slow as adding 1 to an address).
The normal thing when optimizations are enabled would otherwise be to replace the whole thing with the absolute value.
> If not, is there a compiler flag to for gcc to make the static index of an array a static pointer?
Messing around with compiler options is probably not how. If you wish to have a pointer to a fixed address, then this is the usual steps:
- Create a custom segment at a fixed address in the linker script for the specific target.
- Declare your array at file scope and use gcc variable attributes to allocate it inside your custom segment.
- Now
&global_array[1]
is always the same address.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论