C语言基础知识--变量

目录

一、C语言变量

1、局部变量

1)、什么是局部变量

2)、代码示例

3)、代码讲解

2、全局变量

1)、什么是全局变量

2)、代码示例

3)、代码讲解

3、静态变量

1)、全局静态变量

2)、局部静态变量

3)、代码示例

4)、代码讲解

4、const常量

1)、const变量

5、寄存器变量

1)、register变量

2)、代码示例

3)、代码讲解

二、总结


一、C语言变量

本文用到ARM汇编指令,请参考:

ARM常用汇编指令_BIN-XYB的博客-优快云博客

本文用到编译器为在线编译器(ARM-GCC):

Compiler Explorer

1、局部变量

1)、什么是局部变量

局部变量,顾名思义,只在局部区域有效的变量。

局部变量的空间开辟在栈中,在程序运行过程中动态开辟,局部变量的生命周期随着函数调用的开始而开始,随着函数调用的结束而结束。

2)、代码示例
#include <stdio.h>

int test_func(int param0, int param1)
{
    int b = 4;
    return b;
}

int main()
{
    test_func(1, 3);
    return 0;
}

编译后汇编如下:

test_func:
        push    {r7}
        sub     sp, sp, #20
        add     r7, sp, #0
        str     r0, [r7, #4]
        str     r1, [r7]
        movs    r3, #4
        str     r3, [r7, #12]
        ldr     r3, [r7, #12]
        mov     r0, r3
        adds    r7, r7, #20
        mov     sp, r7
        ldr     r7, [sp], #4
        bx      lr
main:
        push    {r7, lr}
        add     r7, sp, #0
        movs    r1, #3
        movs    r0, #1
        bl      test_func
        movs    r3, #0
        mov     r0, r3
        pop     {r7, pc}
3)、代码讲解

在test_func函数中定义局部变量b,且初始化为4,分析test_func汇编代码,如下图圈住地方(对应c语言的语句 int b = 4;):

将立即数4写入寄存器R3中,然后将R3寄存器中值写入栈(R7+12Byte处)中。完成局部变量的空间开辟以及值初始化。

2、全局变量

1)、什么是全局变量

全局变量是在代码文件中定义的全局变量,在整个源文件中皆可访问。如果要在其他源文件中使用该变量,需要使用extern关键字引用。

全局变量的空间开辟在全局变量区,全局变量的生命周期同程序的生命周期相同。

2)、代码示例
#include <stdio.h>
int a = 3;
int test_func(int param0, int param1)
{
    int b = a;
    return b;
}

int main()
{
    test_func(1, 3);
    return 0;
}

编译后汇编如下:

a:
        .word   3
test_func:
        push    {r7}
        sub     sp, sp, #20
        add     r7, sp, #0
        str     r0, [r7, #4]
        str     r1, [r7]
        movw    r3, #:lower16:a
        movt    r3, #:upper16:a
        ldr     r3, [r3]
        str     r3, [r7, #12]
        ldr     r3, [r7, #12]
        mov     r0, r3
        adds    r7, r7, #20
        mov     sp, r7
        ldr     r7, [sp], #4
        bx      lr
main:
        push    {r7, lr}
        add     r7, sp, #0
        movs    r1, #3
        movs    r0, #1
        bl      test_func
        movs    r3, #0
        mov     r0, r3
        pop     {r7, pc}
3)、代码讲解

定义全局变量a,且初始化为3。在test_func函数中定义局部变量b且将全局变量a的值赋予局部变量b,分析汇编代码,如下图圈住地方(对应c语言的语句 int b = a;):

将全局变量a的地址写入寄存器R3中,然后将R3寄存器中所指向地址中的数据读取到R3寄存器中,然后将R3寄存器中值写入栈(R7+12Byte处)中。将局部变量b初始化成全局变量a的值。由以上分析可以看出全局变量并不像局部变量那样保存在栈上,而是定义在数据段上。

3、静态变量

1)、全局静态变量

全局静态变量是指定义在代码文件中的用static修饰的变量,静态全局变量存储在静态变量区,生命周期伴随程序的整个生命周期。只可在定义该变量的源文件中使用,不可在其他源文件中使用extern关键字引用该文件。

2)、局部静态变量

局部静态变量是指在函数内定义的使用static修饰的变量。局部全局变量存储在静态变量区,生命周期伴随程序的整个生命周期。尽可在定义该变量的函数内使用。

3)、代码示例
#include <stdio.h>
static int a = 5;
int test_func(int param0, int param1)
{
    static int b = 2;
    b++;
    a++;
    return b;
}

int main()
{
    int ret = test_func(1, 3);
    printf("b:%d\r\n", ret);
    ret = test_func(1, 3);
    printf("b:%d\r\n", ret);
    return 0;
}

编译后汇编如下:

a:
        .word   5
test_func:
        push    {r7}
        sub     sp, sp, #12
        add     r7, sp, #0
        str     r0, [r7, #4]
        str     r1, [r7]
        movw    r3, #:lower16:b.0
        movt    r3, #:upper16:b.0
        ldr     r3, [r3]
        adds    r2, r3, #1
        movw    r3, #:lower16:b.0
        movt    r3, #:upper16:b.0
        str     r2, [r3]
        movw    r3, #:lower16:b.0
        movt    r3, #:upper16:b.0
        ldr     r3, [r3]
        mov     r0, r3
        adds    r7, r7, #12
        mov     sp, r7
        ldr     r7, [sp], #4
        bx      lr
.LC0:
        .ascii  "b:%d\015\012\000"
main:
        push    {r7, lr}
        sub     sp, sp, #8
        add     r7, sp, #0
        movs    r1, #3
        movs    r0, #1
        bl      test_func
        str     r0, [r7, #4]
        ldr     r1, [r7, #4]
        movw    r0, #:lower16:.LC0
        movt    r0, #:upper16:.LC0
        bl      printf
        movs    r1, #3
        movs    r0, #1
        bl      test_func
        str     r0, [r7, #4]
        ldr     r1, [r7, #4]
        movw    r0, #:lower16:.LC0
        movt    r0, #:upper16:.LC0
        bl      printf
        movs    r3, #0
        mov     r0, r3
        adds    r7, r7, #8
        mov     sp, r7
        pop     {r7, pc}
4)、代码讲解

定义静态全局变量a,且初始化为5。在test_func函数中定义的静态局部变量b为,且初始化为2,分析汇编代码a++(绿框圈住)和b++(红框圈住)语句:

        movw    r3, #:lower16:b.0

        movt    r3, #:upper16:b.0 ; 将变量b的地址写入到R3寄存器

        ldr     r3, [r3];将b的值读取到寄存器R3中

        adds    r2, r3, #1;寄存器R3自增,结果保存到R2寄存器

        movw    r3, #:lower16:b.0

        movt    r3, #:upper16:b.0;将变量b的地址写入到R3寄存器

        str     r2, [r3];R2寄存器中运算结果写入R3寄存器中所指的地址中

变量a分析雷同。静态变量a与b的区别是a可以再整个源文件中访问,b只可以在函数test_func中访问。

4、const常量

1)、const变量

const变量,为只读变量,在编码过程中只可对该变量进行读,不可修改该变量的值。该变量会被存放在常量区,生命周期伴随程序的整个生命周期。

5、寄存器变量

1)、register变量

register变量,为寄存器变量,在编码过程中使用该变量修饰局部变量,告诉编译器将此变量尽量存储在寄存器中,编译器会根据现实情况,来尽可能的降该变量的存储空间开辟在CPU寄存器中,但不是绝对可以开辟在寄存器中。register关键字只可以用来修饰局部变量。

2)、代码示例
#include <stdio.h>

int test_func(int param0, int param1)
{
    register int a = 5;
    int b = a + 2;
    return b;
}

int main()
{
    test_func(1, 3);
    return 0;
}

编译后汇编如下:

test_func:
        push    {r4, r7}
        sub     sp, sp, #16
        add     r7, sp, #0
        str     r0, [r7, #4]
        str     r1, [r7]
        movs    r4, #5
        adds    r3, r4, #2
        str     r3, [r7, #12]
        ldr     r3, [r7, #12]
        mov     r0, r3
        adds    r7, r7, #16
        mov     sp, r7
        pop     {r4, r7}
        bx      lr
main:
        push    {r7, lr}
        add     r7, sp, #0
        movs    r1, #3
        movs    r0, #1
        bl      test_func
        movs    r3, #0
        mov     r0, r3
        pop     {r7, pc}
3)、代码讲解

在test_func函数中定义寄存器局变量a,且初始化为5。定义局部变量b,且初始化为a+2,分析汇编代码(register int a = 5; int b = a + 2;)语句:

        movs    r4, #5;将立即数5写到寄存器R4中

        adds    r3, r4, #2;将R4中的值与立即数2相加,结果保存在寄存器R3中

        str     r3, [r7, #12];,将R3中运算结果保存到栈中(R7+12Byte处)。

由上分析可知,变量a被保存在寄存器中,变量b被保存在栈中。

二、总结

如有问题请批评指出,感谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值