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

网站建设4年前发布
30 0 0

20230305204916f87516d00ec442d0277970e66ce8664cfeaa18470,微信群里有同学问C语言中数组在内存中是怎样表示的,今天就给大家聊聊这个话题。,开局一张图:,20230305205134e76d61166f322b83c724812f51580a11671562888,这个是经典的Linux进程内存布局,通常我们使用的数据存在这样几个地方:,接下来我们分别看一下C语言中的数组在这几个区域是怎样表示的,注意,小风哥的机器是x86 64位。,来看一段极其简单的代码:,我们定义了一个局部变量arr作为int类型的数组,然后分别将100-600写到了数组中,那么数组arr在内存中是怎样表示的呢?,首先我们编译一下:,注意,-fno-stack-protector选项是为了禁止堆栈保护,让汇编更容易懂些。,好啦,一切准备就绪,可以庖丁解牛啦,使用的刀就是gdb,代码面前了无秘密,gdb面前程序的运行时(run time)了无秘密。,用gdb来调试刚刚编译出来的程序,这里看一下arr_on_stack函数的汇编指令:,我们在之前的文章《函数在内存中是怎样表示的?》多次提到过,每个函数在运行起来后都有属于自己的栈帧,栈帧组成栈区,此时arr_on_stack这个函数的栈区在哪里呢?答案就在寄存器rbp中。,我们来看一下rbp寄存器指向了哪里?,啊哈,原来栈帧在0x7ffffffee2a0这个地方,那么我们的数组arr在哪里呢?别着急,这条指令会告诉我们答案:,这行指令的含义是说把100(0x64)放到rbp寄存器减去0x20的地方,显然这就是数组的开头,让我们来计算一下rbp寄存器减去0x20:,因此,我们预测arr应该在0x7ffffffee280这个位置上。,接下来我们用gdb验证一下:,哈哈,怎么样,是不是和我们猜想的一样,数组arr的确就放在了0x7ffffffee280这个位置,是这样存储的:,2023030520491748caf05072460d85b60896b91fd0f409da0624866,这就是C语言中所谓的数组了,无非就是从0x7ffffffee280 到 0x7ffffffee298这一段内存嘛,数组在栈区就是这么表示的!,同样看一段代码:,同样使用# gcc -g -fno-stack-protector a.c编译,然后用gdb加断点在int b = global_array[0]这行代码,看下全局变量global_array的内存位置:,gdb告诉我们数组global_array存放在内存0x601050这个地址上。,注意0x601050这个地址和刚才看到的0x7ffffffee280这个地址相去甚远,为什么呢?,再看下开局那张图:,20230305204917555a98e32097de7b376098da7a98b8c9f04c1a129,全局区几乎在最底部,栈区在最顶部,所以相差很远。,接下来让我们看看0x601050这个内存区域中到底保存了些啥?,我们使用命令x/6wd 0x601050,这个命令告诉gdb从0x601050这个位置开始以32bit为单位用10进制依次打印6次,让我们来看看打印的是什么?,哈哈,怎么样,是不是正是全局变量global_array中存放的内容:2023030520491809d248d728881b4ee7c9994db48152a2860e57711,这就是C语言中所谓的数组了,无非就是从 0x601050到 0x601068这一段内存嘛,数组在全局区就是这么表示的!,来段代码:,使用gdb加断点在int a = arr[0];这行代码,然后打印数组arr的地址:,注意0x602010这个地址,这个地址和刚才的全局数组global_array的地址0x601050比较接近,因为堆区和全局区挨得比较近,可以再回过头看一下开局那张图。,然后我们同样使用x命令查看这个区域的内存内容:,依然不出我们所料,这个区域保存的正是数组的值。,202303052049186605ae744f5657846e5866204eefdc13b7a24b775,这就是C语言中所谓的数组了,无非就是从 0x602010到 0x602028这一段内存嘛,数组在堆区就是这么表示的!,现在你应该明白了吧,C语言中所谓的数组是怎么表示的?很简单,其实也没啥表示,无非就是内存中一段连续的空间,仅此而已。,希望这篇文章对大家理解C语言中的数组有所帮助。

© 版权声明

相关文章