对于初学C语言学者,理解C程内存布局对于我们理解与运用指针非常重要,在笔试中也经常有考题涉及到。
一、总体布局
二、测试验证
1
以下测试在虚拟机Ubuntu18.04下的测试结果,在树莓派(ARM处理器)测试不同之处也会指出。
1.程序各段内存遵循上图顺序内存布局:
结果如下图:
把地址在图上标出:
(图中最低地址和最高地址只是表明内存方向)
由上图看出,栈区在堆区的上面,bss段和数据段data、只读数据段rodata按顺序存放在内存中。唯一区别是命令行参数区的地址比栈区的小,但是比堆区的地址大,所以命令行参数区存放在栈区与堆区中间。
我们在32位树莓派上测试:
可以看到命令行参数区内存也是在栈区与堆区的中间。
2 栈区与堆区内存增长方向
在理论上,栈区的增长方向是向下,堆区是向上,下面在Ubuntu下测试结果:
结果分析出,栈区和堆区都是自低地址向高地址增长的,下面我们在树莓派上测试看;
可以看出,在树莓派上测试结果与在Ubuntu下测试结果不同:栈的增长方向是自上而下,堆的增长是自下而上的。
测试代码:
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
int g_bss_test;
int g_data_value = 10;
char *ptr = "hello word";
int main (int agrv, char **argc)
{
int stack_int;
int stack_intvalue = 1111;
char *heap_ptr = malloc(10);
char *heap_dir = malloc(10);
memset(heap_dir, 0, strlen(heap_dir));
printf("the argument address is: %p, value is :%s \n", &argc, *argc);
printf("the stack_int address is: %p , value is %d \n",&stack_int,stack_int);
printf("the stack_intvalue address is %p, value is %d \n",&stack_intvalue,stack_intvalue);
printf("the heap_ptr address is : %p, value is : %c \n",heap_ptr, *heap_ptr);
printf("the heap_ptr address direction is : %p, value is : %c \n",heap_dir, *heap_dir);
printf("the g_bss_test address is: %p , value is %d \n", &g_bss_test, g_bss_test);
printf("the g_data_value address is: %p , value is %d \n", &g_data_value, g_data_value);
printf("the read only address is : %p, value is : %s \n", ptr,ptr);
printf("the address bits is : %d \n", sizeof(ptr ) );
}
树莓派下测试代码:
#include <stdio.h>
#include <stdlib.h>
int main(int argv, char **argc)
{
int s_test = 1;
int s_direction;
char *h_test = malloc(10);
char *h_direction = malloc(10);
printf("the stack address is : %p \n", &s_test);
printf("the stack direction address is : %p \n", &s_direction);
printf("the argument address is %p \n", &argc);
printf("the heap address is %p \n", &h_test);
printf("the heap direction address is %p \n", &h_direction);
}