Mar*_*ant 7 c stack alignment compiler-optimization
考虑以下程序:
#include <stdio.h>
void some_func(char*, int*, char*);
void stack_alignment(void) {
char a = '-';
int i = 1337;
char b = '+';
some_func(&a, &i, &b); // to prevent the compiler from removing the local variables
printf("%c|%i|%c", a, i, b);
}
Run Code Online (Sandbox Code Playgroud)
它生成以下程序集(由我自己添加的注释,我是程序集的完整新手):
$ vim stack-alignment.c
$ gcc -c -S -O3 stack-alignment.c
$ cat stack-alignment.s
.file "stack-alignment.c"
.section .rdata,"dr"
LC0:
.ascii "%c|%i|%c\0"
.text
.p2align 2,,3
.globl _stack_alignment
.def _stack_alignment; .scl 2; .type 32; .endef
_stack_alignment:
LFB7:
.cfi_startproc
subl $44, %esp
.cfi_def_cfa_offset 48
movb $45, 26(%esp) // local variable 'a'
movl $1337, 28(%esp) // local variable 'i'
movb $43, 27(%esp) // local variable 'b'
leal 27(%esp), %eax
movl %eax, 8(%esp)
leal 28(%esp), %eax
movl %eax, 4(%esp)
leal 26(%esp), %eax
movl %eax, (%esp)
call _some_func
movsbl 27(%esp), %eax
movl %eax, 12(%esp)
movl 28(%esp), %eax
movl %eax, 8(%esp)
movsbl 26(%esp), %eax
movl %eax, 4(%esp)
movl $LC0, (%esp)
call _printf
addl $44, %esp
.cfi_def_cfa_offset 4
ret
.cfi_endproc
LFE7:
.def _some_func; .scl 2; .type 32; .endef
.def _printf; .scl 2; .type 32; .endef
Run Code Online (Sandbox Code Playgroud)
如您所见,有3个局部变量(a,i和b),大小为1字节,4字节和1字节.包括填充,这将是12字节(假设编译器对齐4个字节).
如果编译器将变量的顺序改为(,)a,那么它的内存效率会不会更高?那么只需要8个字节.bi
这里有一个"图形"表示:
3 bytes unused 3 bytes unused
vvvvvvvvvvv vvvvvvvvvvv
+---+---+---+---+---+---+---+---+---+---+---+---+
| a | | | | i | b | | | |
+---+---+---+---+---+---+---+---+---+---+---+---+
|
v
+---+---+---+---+---+---+---+---+
| a | b | | | i |
+---+---+---+---+---+---+---+---+
^^^^^^^
2 bytes unused
Run Code Online (Sandbox Code Playgroud)
是否允许编译器进行此优化(通过C标准等)?
编译器可以根据需要自由布局局部变量.它甚至不需要使用堆栈.
如果它使用堆栈,它可以按照与堆栈上的声明顺序无关的顺序存储局部变量.
是否允许编译器进行此优化(通过C标准等)?
- 如果是的话,为什么不在上面发生?
嗯,这是一个优化吗?
目前尚不清楚.它少了几个字节,但这很少重要.但是在某些体系结构中,char如果它以字对齐的方式存储,则读取它可能会更快.因此,将chars彼此相邻会迫使其中一个至少不进行单词对齐并使其读取速度变慢.
编译器是否允许进行此优化(根据 C 标准等)?
是的。
如果是的话,为什么上面的情况没有发生呢?
它确实发生了。
仔细阅读汇编器的输出。
movb $45, 26(%esp) // local variable 'a'
movl $1337, 28(%esp) // local variable 'i'
movb $43, 27(%esp) // local variable 'b'
Run Code Online (Sandbox Code Playgroud)
变量a位于偏移量 26 处。变量b位于偏移量 27 处。变量i位于偏移量 28 处。
使用您制作的图像,布局现在是:
+---+---+---+---+---+---+---+---+
| | | a | b | i |
+---+---+---+---+---+---+---+---+
^^^^^^^
2 bytes unused
Run Code Online (Sandbox Code Playgroud)