C语言基础知识--变量

2023-10-31

目录

一、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的博客-CSDN博客

本文用到编译器为在线编译器(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被保存在栈中。

二、总结

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C语言基础知识--变量 的相关文章

随机推荐

  • 【从零开始的Java开发】2-9-3 油画商城静态网页案例

    文章目录 项目展示 项目 0 准备工作 1 页眉区的制作 1 1 logo和menu位置的摆放 1 2 menu功能的实现 1 3 menu功能的样式 1 4 登录与注册 1 5 小结 2 正文区的制作 2 1 页眉和banner区 2 2
  • Android Dialog用法

    摘要 创建对话框 一个对话框一般是一个出现在当前Activity之上的一个小窗口 处于下面的Activity失去焦点 对话框接受所有的用户交互 对话框一般用于提示信息和与当前应用程序直接相关的小功能 Android API 支持下列类型 创
  • 什么是结构因果模型

    结构因果模型 结构因果模型简介 定义 历史 因果关系之梯 关联 干预 反事实 因果 因果和相关 类型 必要因 充分因 促成因 模型 因果图 模型元素 连接方式 链 叉 对撞 节点类型 中介变量 混杂因子 工具变量 孟德尔随机化 关联 独立性
  • linux内核编程入门之proc文件读写

    my proc dir proc create myproc 0666 NULL proc ops 在 proc 根目录下创建文件myproc 文件的权限为0666 文件的读写操作定位在proc ops中 具体可以看下面源码 可以使用 ec
  • 蜂群算法论文【matlab代码与仿真】

    一 算法流程 蜂群算法 Bee Algorithm 是一种启发式优化算法 灵感来源于蜜蜂在寻找食物和选择巢穴的行为 这种算法模拟了蜜蜂群体中的集体智能 用于解决各种优化问题 蜂群算法的基本思想是通过模拟蜜蜂的搜索行为来寻找最优解 算法中的蜜
  • 仙境传说RO:添加自定义道具

    仙境传说RO 添加自定义道具 大家好 我是艾西今天和大家聊一下仙境传说RO怎么添加自定义道具 在我们开服时加入一些道具模组等往往会让我们的服务器更有特色以及消费点 那么让我们直接进入正题开始操作 此处我们讲的过程中以红色药水举例 喜欢的可以
  • php弹窗一次,网站广告弹出层(每天弹出一次)

    网站广告弹出层 每天弹出一次 可以有两种做法 一 是标识符存入数据库 二 利用Jquery cookie 我这里做的是比较简单的用到的知识是Jquery cookie 这里要注意的一点是jquery cookie的值 火狐能够获取 IE 3
  • VMware桥接模式无法识别英特尔AX200无线网卡解决办法

    1 先到英特尔网站下载最新驱动 更新网卡驱动适用于 Intel 无线网络卡的 Windows 10 和 Windows 11 Wi Fi 驱动程序 2 到控制面板查看无线网卡属性是否有下图组件 没有的话 依次操作 安装 服务 添加 从磁盘安
  • Unidbg系列--Ollvm字符串解密

    Ollvm字符串解密 原理 使用unidbg框架 模拟调用So文件 并Hook内存写操作 当so解密操作写入内存时 回调获取解密字符串 并将其写入新so文件中 达到反OLLVM字符串加密的目的 解密脚本 package com xCrack
  • openmvs编译

    OpenMVG 和OpenMVS在Widows下使用Vs2019编译 black world 博客园 cnblogs com cmake src G Visual Studio 16 2019 A x64 DCMAKE TOOLCHAIN
  • pyspark-ml学习笔记:模型评估

    问题是这样的 如果我们想基于pyspark开发一个分布式机器训练平台 那么肯定需要对模型进行评估 而pyspark本身自带模型评估的api很少 想进行扩展的话有几种方案 1 使用udf自行编写代码进行扩展 2 使用现有的 像sklearn中
  • CentOS安装Docker

    Docker是一个开源的容器引擎 它有助于更快地交付应用 Docker可将应用程序和基础设施层隔离 并且能将基础设施当作程序一样进行管理 使用 Docker可更快地打包 测试以及部署应用程序 并可以缩短从编写到部署运行代码的周期 CentO
  • 相机标定实战之双目标定

    相机标定原理 文章目录 相机标定原理 前言 一 采集图像 二 基于Matlab单双目标定流程 采集棋盘图 三 基于OpenCV Python双目标定流程 检测棋盘格角点 对角点进行亚像素精细化 单目标定 双目标定 双目校正 保存标定参数 读
  • 服务器系统怎么设置第一启动项,服务器怎么设置启动项

    服务器怎么设置启动项 内容精选 换一换 华为云帮助中心 为用户提供产品简介 价格说明 购买指南 用户指南 API参考 最佳实践 常见问题 视频帮助等技术文档 帮助您快速上手使用华为云服务 您需要在源端服务器上安装迁移Agent并且输入目的端
  • java: 非法字符: ‘\ufeff‘解决方法

    出现问题 在使用idea时候会出现java 非法字符 ufeff 这样的情况 原因 出现这样的问题来源于这个BOM 一般在编写时候会给你默认添加这样的一个BOM头 是隐藏起来的 编译时候会给出现编码混乱问题 详见了解BOM 隐藏字符 百度百
  • 三调与二调图斑叠加分析,筛选不同地类面积占比,筛选举证图斑

    主要步骤 标识数据 叠加分析 用标识 生成所有相交图斑 属性有原图斑的地类和国家的地类 以及原图斑的面积 生成的面域 增加4个字段 图斑的三调一级类 图斑的国家NYYPDL 是否相同 标识后的图斑面积 转换三调地类为二调的一级类 转换国家地
  • 《最强大脑第九季》C#手撸傅立叶残影题目

    在最新一季的最强大脑总决赛中 有一个比赛项目 傅立叶残影 感觉印象深刻 原理就是五根针首尾相连 按照自身的转速和杆长运动 根据提供的每根杆的转速和杆长来判断出尾部运动的残影轨迹 原理比较简单 就是一个连杆运行 好吧 知道原理就可以动手开始撸
  • 整数除法JS

    param number a param number b return number var divide function a b const MIN Math pow 2 31 const MAX Math pow 2 31 1 判断
  • Redis的事务学习及用Redis实现乐观锁,redis数据类型总结

    一 Redis的事务操作 1 Redis 事务可以一次执行多个命令 并且带有以下三个重要的保证 批量操作在发送 EXEC 命令前被放入队列缓存 收到 EXEC 命令后进入事务执行 事务中任意命令执行失败 其余的命令 依然被执行 但是如果队列
  • C语言基础知识--变量

    目录 一 C语言变量 1 局部变量 1 什么是局部变量 2 代码示例 3 代码讲解 2 全局变量 1 什么是全局变量 2 代码示例 3 代码讲解 3 静态变量 1 全局静态变量 2 局部静态变量 3 代码示例 4 代码讲解 4 const常