目录

  • ​​背景​​
  • ​​测试​​
  • ​​总结​​
  • ​​局部变量压栈顺序​​
  • ​​参考​​

背景

测试

#include <stdio.h>
#include <stdint.h>


struct struct_a {
short a;
char b[10];
uint16_t flag;
uint32_t c;
};

struct struct_b {
char name[32];
uint32_t b;
uint64_t c;
uint16_t d;
};

int main(int argc, const char *argv[])
{
char char_a;
short short_a;
int int_a;
float float_a;
double double_a;
struct struct_a aa;
unsigned int uint_a;
long int lint_a;
long long int dlint_a;
struct struct_b bb;
struct struct_a aas[3];

printf(" &char_a : %p\n",&char_a);
printf(" &short_a : %p\n",&short_a);
printf(" &int_a : %p\n",&int_a);
printf(" &float_a : %p\n",&float_a);
printf("&double_a : %p\n",&double_a);
printf(" &unsigned_int_a : %p\n",&uint_a);
printf(" &long_int_a : %p\n",&lint_a);
printf("&long_long_int_a : %p\n",&dlint_a);
printf("&struct_b bb : %p\n",&bb);
printf("&struct_a aa: %p\n",&aa);


int i = 0;
printf("address-index: %p\n", &i);
uint32_t arr[7] = {0};
if (1) {
int j;
printf("address-j: %p.\n", &j);
struct struct_b bbs[3];
for (; i < 3; i++)
{
j += i;
arr[i] = 0;
printf("address-struct bbs[%d]: %p\n", i, &(bbs[i]));
printf("address-struct aas[%d]: %p\n", i, &(aas[i]));
printf("address-arr[%d]: %p\n", i, &(arr[i]));
}
}
return 0;
}
编译:
gcc -o test_gcc_statck_address -O2 test_gcc_statck_address.c

结果:
./test_gcc_statck_address
&char_a : 0x7fff62937e71
&short_a : 0x7fff62937e72
&int_a : 0x7fff62937e74
&float_a : 0x7fff62937e78
&double_a : 0x7fff62937e88
&unsigned_int_a : 0x7fff62937e7c
&long_int_a : 0x7fff62937e90
&long_long_int_a : 0x7fff62937e98
&struct_b bb : 0x7fff62937ee0
&struct_a aa: 0x7fff62937ea0
address-index: 0x7fff62937e80
address-j: 0x7fff62937e84.
address-struct bbs[0]: 0x7fff62937f60
address-struct aas[0]: 0x7fff62937f20
address-arr[0]: 0x7fff62937ec0
address-struct bbs[1]: 0x7fff62937f98
address-struct aas[1]: 0x7fff62937f34
address-arr[1]: 0x7fff62937ec4
address-struct bbs[2]: 0x7fff62937fd0
address-struct aas[2]: 0x7fff62937f48
address-arr[2]: 0x7fff62937ec8

总结

局部变量压栈顺序

前提条件, 开启编译优化(-O2/-O3)时, 此时默认启用堆栈保护(-fstack-protector),局部变量压入栈中的顺序如下所示:

1> 栈的生长方向为由高地址到低地址,存储局部变量的顺序为先存放数据类型大的。
即数据类型大的存放在栈中的高地址。
结构体作为一个整体计算数据类型的大小;
数组作为一个整体计算数据类型的大小。
2》放入栈中的顺序和局部变量的定义先后顺序以及作用于没有关系。
3》同类型大小按定义变量的先后顺序,内存地址会增加。
即:同类型大小的,后定义的变量放在高地址。

参考

https://shenbaise9527.com/2020/11/03/c-variables-function-stack/