嵌入式C语言编程中经验教训总结(一) 详解const、static和volatile

34 篇文章 2 订阅
33 篇文章 2 订阅


嵌入式C语言编程中经验教训总结

C语言是目前主流的系统编程语言,而嵌入式C语言,是C语言在嵌入式系统中的扩展,不同于pc平台,嵌入式的cpu处理器可以说是五花八门,高中低档齐全,架构也不相同,所以,嵌入式的c程序编写往往具有鲜明的系统特征,例如会涉及到操作硬件,需要自己编写操作硬件的函数,可用的内存就是芯片上的ram空间,处理器的性能大体决定了程序的运行速度,处理器的资源配置也决定了可用资源的多少。嵌入式C程序在编译链接完成后,一般会有如下的输出:

在这里插入图片描述
在Program Size行中我们可以看到:

  1. Code,全程为Readonly code Memory,为只读代码段
  2. RO-data,全程为Readonly data Memary 只读数据段
  3. RW-data,readwrite data Memary 读写数据段
  4. ZI-data,Zero Initialize,没有初始化,默认初始化0的可读写变量的大小

通常地说,我们编写的代码大小,也就是最终烧写到处理器FLASH中的空间就是:Code + RO Data + RW Data,而程序运行的时候,芯片内部RAM使用的空间为: RW Data + ZI Data,在嵌入式的c语言中,我们如何确定或分配这些空间昵,这就是const、static和volatile的主要作用。

(一) 详解const、static和volatile

1、static关键字的作用

在嵌入式C语言中static有下性质:

  • (1)声明变量:
    在函数体中,一个被声明为静态的变量在这一函数被调用过程中只会被分配一次内存,且整个运行期间不会重新分配;在函数体外、本源文件内,该变量只能该源文件内的所有函数访问,但不能被其他源文件的函数访问。它是一个本地的全局变量,即便extern外部声明也不可以。

    (2) 声明函数
    在某源文件内,一个被声明为静态的函数仅仅只可以被该源文件的其它函数调用。也就是说,这个函数被限制在声明它的源文件的本地范围之内使用。
    举例如下:
    int fun_Test(void)
    {
    unsigned char test_A=0;
    static unsigned char test_B=0;
    test_A++;
    test_B++;
    }
    调用上面的fut_Test()函数就会发现,每次调用该函数的时候,test_A++被执行后,其值只能是1;test_B就会一直的加下去,直到加到255,达到最大值溢出变成0,也就是说,普通的变量在执行完函数后,其内存的空间将会被释放,但是Static所修饰的变量的内存空间将不会被释放,虽然调用函数的时候,有对test_B进行了初始化,语句也会被跳过。

2、volatile关键字的性质

volatile 中文解释是易变的,作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值。在我们的编辑器中,常常会将我们的代码优化,提高代码的执行速度,但如果有一个语句没有写操作,或者是读取操作,编辑器就自作聪明的保存了该内存空间的某一时刻的值, 用于以后的计算,虽然该内存单元中内容改变了,但是程序中用到的变量还是该时刻的保存值,多以会出现一些意想不到的错误,而Volatile的作用就是提醒编译器,这个内存单元空间中的内容是在变动的,编译器优化的时候每次都从变量的内存地址读取,而不是从寄存器或者cache缓存中读取。常常在下面几种情况下,须使用volatile:

1:多线程环境下,一个线程使用的全局变量,但是他的值会被其他线程更新的情况下。

  1. 变量可能被中断处理程序更新

3:对数据采集类应用,外部传感器数据映射到内存单元的寄存器

如果系统有完备的信号量、中断或消息机制,volatile并非不可或缺,但volatile关键字提供了一个简单可靠的快速响应外界变化的方法,虽然反复操作效率有点低。

3、const关键字的作用

const定义的变量,也称常量,更准确的说const变量一旦初始化完成后,是不能被修改的,始终都是不变的,一旦申明后就不能被修改了,嵌入式c语言中 ,const 全局变量存储在RO Data数据段,而const局部变量存储在栈中,代码块结束时释放。

嵌入式程序中,在存储空间分配上,变量加const修饰符,会存储在flash中而不是ram中,通常,flash空间会比ram空间大好多倍,这就有效的节省了ram空间的占用。
例如:const double PI = 3.141599265;

上面定义了const变量PI,定义后,在其他程序中,是无法对PI进行修改赋值的,这就保证了整个 系统中PI的一致性,不会因为其他有的地方重新定义PI=3.14等带来的精度误差。

4关键字的组合使用

上面的关键字也可以组合使用,例如:
static const规定变量在当前的模块中是只读的变量,无法被全局中被其他模块读取。例如对公司log图片点阵,我们当然不希望在不同模块中展示的log会出现不一致,如果我们如下定义:

static const unsignedi char LogDitArray[16384] ={0x00,0x00,0xC0,0xC0,0xC0,0x80,0x00,0x80,
。。。 。。。
0x00,0x00,0xC0,0xC0,0xC0,0x80,0x00,0x10
}

编译之后可在.map文件看到其分配到flash存储空间,且只能在本模块使用

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
### 回答1: 好的,我知道了。下面是C语言定义结构体并申明一个该结构体变量的示例代码: ``` #include <stdio.h> // 定义结构体 struct Student { char name[20]; int age; float score; }; int main() { // 声明结构体变量 struct Student stu; // 对结构体变量进行赋值 strcpy(stu.name, "Tom"); stu.age = 18; stu.score = 90.5; // 输出结构体变量的值 printf("name: %s\n", stu.name); printf("age: %d\n", stu.age); printf("score: %.1f\n", stu.score); return 0; } ``` 在这个示例代码,我们定义了一个名为`Student`的结构体,该结构体包含了三个成员:`name`、`age`和`score`。然后在`main`函数,我们声明了一个名为`stu`的`Student`类型变量,并对其进行了赋值。最后,我们输出了这个结构体变量的成员值。 ### 回答2: C语言可以用关键字struct来定义结构体,并使用typedef关键字给结构体取一个别名,方便后续使用。 具体申明一个该结构体变量的方式为: 1. 首先,我们需要定义结构体的成员变量和成员函数(如果有的话)。例如,我们定义一个结构体Person,其包括姓名和年龄作为成员变量。 ```c typedef struct { char name[20]; int age; } Person; ``` 2. 接下来,我们就可以使用该结构体定义一个结构体变量了。例如,我们定义一个名为person1的结构体变量,并为其成员变量赋值。 ```c int main() { Person person1; // 定义一个Person类型的结构体变量person1 strcpy(person1.name, "张三"); person1.age = 20; printf("姓名:%s,年龄:%d\n", person1.name, person1.age); return 0; } ``` 以上代码定义了一个名为person1的结构体变量,并为其成员变量赋值。最后使用printf函数打印出了person1的姓名和年龄。 注意:在使用结构体变量之前,需要先定义结构体。在定义结构体变量时,可以直接使用结构体的别名。结构体变量的成员变量可以通过`.`(点操作符)来访问。 ### 回答3: C语言定义结构体的关键字是"struct",结构体是一种自定义的数据类型,用于存储不同数据类型的集合。 结构体的定义格式为: ```c struct 结构体名称 { 数据类型 成员1; 数据类型 成员2; ... }; ``` 其,结构体名称是自定义的,根据需求命名。 例如,我们定义一个结构体"Person",包含姓名和年龄两个成员: ```c struct Person { char name[20]; int age; }; ``` 在定义结构体之后,我们可以声明一个该结构体变量,即为结构体分配内存空间,并且可以操作结构体成员变量。 例如,声明一个"Person"类型的变量person: ```c struct Person person; ``` 在此之后,我们可以为结构体成员变量赋值,如: ```c strcpy(person.name, "张三"); person.age = 20; ``` 这样,我们就定义并声明了一个名为"person"的"Person"类型的结构体变量。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cyjbj

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值