C语言数组在内存中是怎样表示的?

最近群里有位同学问“C语言中数组在内存中是怎样表示的”,今天我们就来聊一聊这个话题。

开局一张图:

C语言数组在内存中是怎样表示的?_第1张图片

如上图所示,这是经典的Linux进程内存布局,通常我们使用的数据存在这样几个地方:

  • 栈区,Stack

  • 全局区,Global

  • 堆区,Heap

接下来,我们分别看一下C语言中的数组在这几个区域是怎样表示的(注意:这里的机器是x86 64位)。

1、数组与栈区

先来看一段极其简单的代码:

C语言数组在内存中是怎样表示的?_第2张图片

我们定义了一个局部变量arr作为int类型的数组,然后分别将100-600写到了数组中。那么,数组arr在内存中是怎样表示的呢?

首先,我们编译一下:

注意,-fno-stack-protector选项是为了禁止堆栈保护,让汇编更容易懂些,关于堆栈保护这个话题可以参考这篇文章《黑客攻防:缓冲区溢出攻击与堆栈保护》。

好啦,一切准备就绪,可以庖丁解牛啦,使用的刀就是gdb,代码面前了无秘密,gdb面前程序的运行时(run time)了无秘密。

用gdb来调试刚刚编译出来的程序,这里看一下arr_on_stack函数的汇编指令:

C语言数组在内存中是怎样表示的?_第3张图片

我们在之前的文章多次提到过,每个函数在运行起来后都有属于自己的栈帧,栈帧组成栈区,此时arr_on_stack这个函数的栈区在哪里呢?答案就在寄存器rbp中。

我们来看一下rbp寄存器指向了哪里?

 啊哈,原来栈帧在0x7ffffffee2a0这个地方,那么我们的数组arr在哪里呢?别着急,这条指令会告诉我们答案:

 这行指令的含义是说把100(0x64)放到rbp寄存器减去0x20的地方,显然,这就是数组的开头,让我们来计算一下rbp寄存器减去0x20:

因此,我们预测arr应该在0x7ffffffee280这个位置上。

接下来,我们用gdb验证一下:

 哈哈,怎么样,是不是和我们猜想的一样,数组arr的确就放在了0x7ffffffee280这个位置,是这样存储的:

C语言数组在内存中是怎样表示的?_第4张图片

 这就是C语言中所谓的数组了,无非就是从0x7ffffffee280 到 0x7ffffffee298这一段内存嘛,数组在栈区就是这么表示的!

2、数组与全局区

同样看一段代码:

C语言数组在内存中是怎样表示的?_第5张图片

 同样使用# gcc -g -fno-stack-protector a.c编译,然后用gdb加断点在int b = global_array[0]这行代码,看下全局变量global_array的内存位置:

gdb告诉我们数组global_array存放在内存0x601050这个地址上。

注意,0x601050这个地址和刚才看到的0x7ffffffee280这个地址相去甚远,这是为什么呢?

再看一下开局那张图:

C语言数组在内存中是怎样表示的?_第6张图片

全局区几乎在最底部,栈区在最顶部,所以相差很远。

接下来,让我们看看0x601050这个内存区域中到底保存了些啥?

我们使用命令x/6wd 0x601050,这个命令告诉gdb从0x601050这个位置开始以32bit为单位用10进制依次打印6次,让我们来看看打印的是什么?

 哈哈,怎么样,是不是正是全局变量global_array中存放的内容:

C语言数组在内存中是怎样表示的?_第7张图片

 这就是C语言中所谓的数组了,无非就是从 0x601050到 0x601068这一段内存嘛,数组在全局区就是这么表示的!

3、数组与堆区

再来段代码:

C语言数组在内存中是怎样表示的?_第8张图片

 使用gdb加断点在int a = arr[0];这行代码,然后打印数组arr的地址:

注意,0x602010这个地址和刚才的全局数组global_array的地址0x601050比较接近,因为堆区和全局区挨得比较近,可以再回过头看一下开局那张图。

然后,我们同样使用x命令查看这个区域的内存内容:

 依然不出我们所料,这个区域保存的正是数组的值。

C语言数组在内存中是怎样表示的?_第9张图片

这就是C语言中所谓的数组了,无非就是从 0x602010到 0x602028这一段内存嘛,数组在堆区就是这么表示的!

现在你应该明白了吧,C语言中所谓的数组是怎么表示的?很简单,其实也没啥表示,无非就是内存中一段连续的空间,仅此而已。

希望这篇文章对大家理解C语言中的数组有所帮助。

【学习技术群769843038】

【网盘免费资料包,需要的自行领取】:

嵌入式物联网 22个STM32项目、大赛作品,【华清远见发放资料包】http://makerschool.mikecrm.com/f4wjYBB

C语言数组在内存中是怎样表示的?_第10张图片

【下方分享一些免费教程资料,大家感兴趣的可以看一下】:

C语言编程基础 

提升C编程能力

指针

C语言控制led灯

C语言实现面向对象编程

C语言与数据结构的经典实战案例

Linux C语言高级开发

必备Linux命令和C语言基础

嵌入式操作系统uC/OS

你可能感兴趣的:(嵌入式开发,stm32,物联网开发,jvm,嵌入式硬件,stm32,c语言,linux)