Gur*_*ddy 5 c arrays loops memory-management
我在for循环中声明了一个数组,并尝试打印其基地址。
#include<stdio.h>
int main(){
int n=16;
for(int i=1;i<=n;i++){
int a[i];
int b[16];
int c[n];
printf("%p %p %p\n",(void *)a,(void *)b,(void *)c);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出如下:
0x7fffe6191740 0x7fffe6191770 0x7fffe6191700
0x7fffe6191740 0x7fffe6191770 0x7fffe6191700
0x7fffe6191740 0x7fffe6191770 0x7fffe6191700
0x7fffe6191740 0x7fffe6191770 0x7fffe6191700
0x7fffe6191730 0x7fffe6191770 0x7fffe61916f0
0x7fffe6191730 0x7fffe6191770 0x7fffe61916f0
0x7fffe6191730 0x7fffe6191770 0x7fffe61916f0
0x7fffe6191730 0x7fffe6191770 0x7fffe61916f0
0x7fffe6191720 0x7fffe6191770 0x7fffe61916e0
0x7fffe6191720 0x7fffe6191770 0x7fffe61916e0
0x7fffe6191720 0x7fffe6191770 0x7fffe61916e0
0x7fffe6191720 0x7fffe6191770 0x7fffe61916e0
0x7fffe6191710 0x7fffe6191770 0x7fffe61916d0
0x7fffe6191710 0x7fffe6191770 0x7fffe61916d0
0x7fffe6191710 0x7fffe6191770 0x7fffe61916d0
0x7fffe6191710 0x7fffe6191770 0x7fffe61916d0
Run Code Online (Sandbox Code Playgroud)
为什么数组的基地址每次都会更改?是否为每次迭代分配内存。如果是这样,为什么地址在4次迭代中没有变化?
请说明之间的区别a,b以及c声明,内存分配和基址之间的区别。
这些数组具有自动存储时间,从概念上讲,每次执行循环{ … }内的语句时,都会为每个数组创建一个新实例for。由于在各种迭代中,您需要为数组请求不同的大小a,因此C实现将其放置在内存中的其他位置以为其元素留出空间是完全合理的。您的C实现似乎以16个字节的块为单位,以表示它为数组保留的内存量或对齐方式。这可能是堆栈管理的结果,因为阵列a本身可能不需要对齐或块大小。
很可能,的分配a,b并c通过,在由C标准规定的抽象计算机,的寿命的事实会受到影响b,只要该块的执行开始的开始,但的寿命a和c开始时执行(“对照” )到达定义它们的语句。这是因为C 2018 6.2.4规定了具有自动存储持续时间且长度不可变的对象在进入关联的块时开始生效(第6段),而具有可变长度的此类对象在声明时具有开始寿命(第7段)。因此,当代码被写入时,b开始第一寿命,然后a,再c。
该分配顺序影响c放置位置,但不影响b放置位置。由于b是先创建的,所以它在堆栈上“更早”(位于较高的地址处,这意味着它获得的地址尚未受到的影响a)。由于c是在以后创建的,因此它在堆栈上“较晚”(在较低的地址处,这意味着它将获得受其大小影响的地址a)。C标准在技术上并不需要此顺序,因为C实现可以根据需要安排位置,只要获得与C标准定义的结果相同的结果即可。但是,看来您的实现遵循了C'S抽象的计算机模型忠实,创造b第一,然后a,然后c。
此外,打印对象地址的正确方法是使用%p格式规范并将地址转换为void *:
printf("%p %p %p\n", (void *) a, (void *) b, (void *) c);
Run Code Online (Sandbox Code Playgroud)