编译器 Baremetal (arm-none-eabi) - 编译器实现

Compiler Baremetal (arm-none-eabi) - Compiler Implementation

通常的做法是在函数的入口点声明堆栈变量(分配在执行堆栈上而不是动态或静态的变量)而不是与函数内部的指令混合。 请参阅示例 1.a 和 1.b。 这有助于提高可读性,甚至需要使用较旧的语言。

现代 C/C++ 不再需要它(..但仍然是很好的做法)。

不过我的问题是: 如果堆栈变量在函数内部而不是在入口点,编译器如何解决它。 请参阅示例 2.a 和 2.b 我可以想象他是如何解决它的。 实际发生了什么?

1.a) Example (Common Practice / Best Practice)

void main()
{
    int a = 3;      // best practice
    bool c = false; // best practice

    a += 16;

    if(a == 5)
    {
        c=false;
    }
}

...而不是...

1.b) Example (Uncommon)

void main()
{
    int a = 3;
    a += 16;

    bool c = false; // variable after some instructions executed..
    if(a == 5)
    {
        c=false;
    }
}

2.a) Possible compiler solution (A)

void main()
{
    int a = 3;
    a += 16;

    bool c = false; // COMPILER CUTS THIS LINE AND MOVES IT UP UNDER "int a = 3;"
    if(a == 5)
    {
        c=false;
    }
}

2.B) Possible compiler solution (B)

void main()
{
    int a = 3;
    a += 16;

    { // COMPILER ADDS SUBSECTION IN ORDER TO INTRODUCE NEW VARIABLES ON STACK
        bool c = false; 
        if(a == 5)
        {
            c=false;
        }
    }
}

编译器何时、如何以及在何处实例化或分配此类变量完全取决于实现。它可能会在函数开始时为所有变量创建一个堆栈帧,或者它可能会在声明点扩展堆栈帧,或者它可能根本不使用堆栈而是使用寄存器存储。

该语言只要求实现正确的语义;该变量在声明之前不在 范围 中(即不能被代码引用),并且范围在它所在的块结束 } 之后结束宣布。