繁体   English   中英

局部变量和数组将如何存储在堆栈中?

[英]How will the local variables and arrays stored in stack?

[https://i.stack.imgur.com/kfU6n.png ][1]

#include<stdio.h>
int main()
{
    int x = 23;
    int y = 24;
    int z = 25;
    int asar= 26;
    int a[5];    
    int p = 15;
    int q = 16;
    int r = 17;
    a[11]=56;
    a[10]=57;
    a[9]=58;
    a[8]=59;
    a[7]=60;
    a[6]=61;
    a[5]=62;
  
    printf("\t x=%d, y=%d, z=%d,asar=%d, p=%d, q=%d, r=%d \n", x, y, z, asar, p, q, r);

    return 0;
}

我试图越过数组的边界,这会导致未定义的行为,但在这里我发现所有超出数组边界的值都按最高索引值的顺序复制
11被复制到x中(第一个声明)
10被复制到y (第二次声明)
9被复制到z中(第三次声明)
8被复制到asar (第四次声明)
7被复制到p中(第五次声明)
6被复制到q中(第六次声明)
5被复制到r中(第七次声明)

除了a之外,总共还有 7 个其他变量,我已经将a限制恰好超过了7 个(4+7=11),我得到的输出为: x=56,y=57,z=58,asar=59 , p=60, q=61, r=62
这背后有什么逻辑吗?
不要惊讶我为什么考虑堆栈中的内存分配,因为除了a之外有7 个变量,超过7 个值被一个接一个地复制。 至少对于我来说,当额外变量的数量等于界限超出时,这在每种情况下都是正确的。
对此是否有任何合乎逻辑的解释,或者这个问题毫无价值?

虽然auto变量几乎总是存储在堆栈中,但 C 标准并未强制执行此操作。

对于这样一个没有可变长度数组类型的对象[具有自动存储持续时间] ,它的生命周期从进入与其关联的块开始,直到该块的执行以任何方式结束。 (进入封闭的块或调用函数会暂停,但不会结束当前块的执行。)如果递归地进入块,则每次都会创建对象的新实例。 对象的初始值是不确定的。 如果为对象指定了初始化,则在执行块时每次到达声明时都会执行该初始化; 否则,每次达到声明时,该值变得不确定。

[6.2.4 对象的存储期限,C11]

最符合描述的数据结构确实是堆栈,但标准中没有定义,也没有特定的顺序来存储变量。 CPU 通常要求数据以某种方式对齐以快速访问它们,并且编译器可能(并且将)重新排序它们以减少未使用的地址。 在代码中的某处添加char可能会改变变量的内部顺序。

此外,尝试从其他对象地址访问对象是未定义的行为。 即使你“幸运”并让它以你想要的方式工作,它也可能在以后因为一些看似无关的原因而中断。 例如,通过更改优化级别,编译器可能会删除或合并某些变量,或者将它们放在您无法访问的寄存器中。 利用未定义的行为从来都不是一个好主意。

如果您需要确保数据的特定顺序,您可以使用struct ,它的顺序是有保证的。

正如 6.2.5 中所讨论的,结构是由一系列成员组成的类型,其存储按有序序列分配,而联合是由一系列成员的存储重叠组成的类型。

[6.7.2.1 结构和联合说明符,C99]

通过struct对象指针访问成员是有效的,但编译器可以在成员之间插入填充。 offsetof()宏是正确访问它们所必需的。 (相关:http: //www.catb.org/esr/structure-packing/

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM