0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

C语言之const和volatile的深度学习

电子设计 来源:电子设计 作者:电子设计 2020-12-24 16:13 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

关于const的用法,现在大概前前后后应该写了有两篇文章,以前学习的时候,用法体会不是那么深刻,为啥这么说呢,因为在学习c++的时候,会发现const关键字有新的玩法,关于这个新的玩法,大家可以去看最近学习总结写的c++文章专辑。

一、const的用法:

1、const只读变量:

const修饰的变量是只读的,本质上还是变量

const修饰的局部变量在栈上分配空间

const修饰的全局变量在全局数据区分配空间

const只在编译期有用,在运行期没有用

注:const修饰的变量不是真的常量,它只是告诉编译器该变量不能出现在赋值符号的左边

2、const全局变量的分歧:

在现代c语言编译器中,修改const全局变量将导致程序崩溃

标准c语言编译器不会将const修饰的全局变量存储于只读存储区中,而是存储于可修改的全局数据区,其值依然可以改变

3、代码示例:

(1)只读变量代码示例:

#include <stdio.h>
int main()

const int a =10;
printf("a = %d",a);
a=20;
printf("a = %d",a);

return 0;

运行结果:

test.c: In function ‘main’:
test.c:8:4: error: assignment of read-only variable ‘a’
a=20;

注解:显示这个结果很正常,变量a被const修饰了,它就成了只读的。

(2)如果对变量a的值进行修改:

#include <stdio.h>
int main()

const int a =10;
int *p =(int *) &a;
printf("a = %d",a);
*p=20;
printf("a = %d",a);
return 0;

运行结果:

root@txp-virtual-machine:/home/txp# ./a.out
a = 10
a = 20

注解:通过指针的方式,就能够把a的值进行修改,这也论证了“const修饰的变量是只读的,本质上还是变量”这句话

(3)const修饰全局变量:

代码版本一

#include <stdio.h>
const int b = 40;
int main()



printf("b = %d",b);
b=20;
printf("b = %d",b);
return 0;

输出结果:

root@txp-virtual-machine:/home/txp# gcc test.c
test.c: In function ‘main’:
test.c:10:4: error: assignment of read-only variable ‘b’
b=20;

注解:跟const修饰栈上的变量用法一样

代码版本二

#include <stdio.h>
const int b = 40;
int main()

int *p =(int *) &b;
printf("b = %d",b);
*p=20;
printf("b = %d",b);
return 0;

运行结果:

root@txp-virtual-machine:/home/txp# ./a.out
b = 40
Segmentation fault (core dumped)

注解:这里出现了段错误,这也验证了我们上面所说的“修改const全局变量将导致程序崩溃”。

同时为了验证“标准c语言编译器不会将const修饰的全局变量存储于只读存储区中,而是存储于可修改的全局数据区,其值依然可以改变”这句话,我把这段代码放到dev c++上进行试验:

说明:我这个版本的编译器支持标准c语言,所以没导致程序崩溃,能够正常运行

4、const的本质

c语言中的const使得变量具有只读属性

现代c编译器中的const将具有全局生命周期的变量存储于只读存储区,不是放在全局数据区

注:const不能定义真正意义上的常量;同时这里注意static关键字修饰的变量,它的生命周期和全局变量一样。

代码示例:

#include <stdio.h>
const int Array[5] = {0};
void fun(int *p,int v)

*p=v;

int main()

int const i =1;
const static int j =2;
int const array[5] = {0};
fun((int *)&i,1);
fun((int *)&j,2);
fun((int *)&array[2],3);
fun((int *)&Array[1],4);
return 0;

输出结果:

root@txp-virtual-machine:/home/txp# ./a.out
Segmentation fault (core dumped)

注解:这里会有段错误,错误出现在const+static修饰的j变量对其进行修改,还有const修饰的全局数组。

5、const修饰函数参数和返回值

const修饰函数参数表示在函数体内不希望改变参数的值

const修饰函数返回值表示返回值不可改变,多用于返回指针的情形

在c语言中的字符串字面量存储于只读存储区中,在程序中需要使用const char* 指针,例如:

const char * s = "TXP嵌入式";//字符串字面量

代码示例:

#include <stdio.h>
const char*fun(const int i)

i=8;
return "TXP";

int main()

const char * p=fun(0);
printf("%s",p);
p[1]='_';
printf("%s",p);
return 0;

输出结果:

root@txp-virtual-machine:/home/txp# gcc test.c
test.c: In function ‘fun’:
test.c:5:4: error: assignment of read-only parameter ‘i’
i=8;

test.c: In function ‘main’:
test.c:12:5: error: assignment of read-only location ‘*(p + 1u)’
p[1]='_';

注解:上面这样写,肯定有问题。

代码进化:

#include <stdio.h>
const char*fun(const int i)

// i=8;
return "TXP";

int main()

const char * p=fun(0);
printf("%s",p);
// p[1]='_';
// printf("%s",p);
return 0;

输出结果:

root@txp-virtual-machine:/home/txp# ./a.out
TXP

二、volatile的用法

老实说,这个关键字在面试题目里面经常会出现,但是平时学习的时候,如果你没有真正理解这其中的含义,在笔试的时候,脑袋里面可能依稀是记得有那么几个结论,但是有时候吧,一紧张就把结论给忘了,也不是不可能,所以说,咋们还是老实一点,得真正把它原理搞明白才行,这样上来战场就不怕了,以后写代码也就少一点bug。

1、volatile的常用结论(volatile英文本意就是易变的意思)

这里我先给结论,然后再给一个例子,把这个例子的讲明白,所有结论就都明白了。

volatile可理解为“编译器警告指示字”

volatile告诉编译器必须每次去内存中取变量值

volatile主要修饰可能被多个线程访问的变量

volatile也可以修饰可能被未知因素更改的变量

volatile可以修饰一个中断子程序中会访问到的非自动变量

2、分析原理

大家可能平时在博客学习,都会发现讲解编译器优化的,然后加了volatile关键来修饰变量,就告诉编译器不要去优化这个变量了,那么这里的优化到底是什么意思呢?

从字面上来理解优化两个字,意思就是最优值(变量的值不会改变),这里我用一个简单代码来说明一下:

#include <stdio.h>
int main()

int a =1;//volatile int a =0;

while(a)



说明:上面的代码,如果变量a没有加volatile修饰的话,编译器就会优化它(也就是a的值一直不变),所以while就一直死循环;然后我如果加了volatile来修饰的话,编译器就不会去优化变量a,不优化的意思就是说,变量a的值可能就会改变,while就不会一直死循环。

当然这里为了好理解,我说的不是很专业,没有从寄存器和内存的角度去说。(我也不想那么去讲解,简单理解了就行)

总之一句话:上面的结论中,volatile修饰的都是变量,变量就可能改变,不会被编译器优化;只是说我们上面的结论应用场景不同而已。

三、总结

const使得变量具有只读属性

const不能定义真正意义上的常量

const将具有全局生命周期的变量存储于只读存储区

volatile强制编译器减少优化,必须每次从内存中取值

好了,今天的分享就到这里,如果文章中有错误或者不理解的地方,可以交流互动,一起进步。我是txp,下期见!

审核编辑:符乾江
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • C语言
    +关注

    关注

    183

    文章

    7649

    浏览量

    146340
  • volatile
    +关注

    关注

    0

    文章

    46

    浏览量

    13818
  • CONST
    +关注

    关注

    0

    文章

    45

    浏览量

    8835
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    深度学习为什么还是无法处理边缘场景?

    [首发于智驾最前沿微信公众号]虽然自动驾驶车辆已经完成了数百万公里的行驶测试,深度学习也已被普遍应用,但依然会在一些看似简单的场景中犯下低级错误。比如在遇到一些从未见到过的边缘场景时,系统可能会
    的头像 发表于 05-04 10:16 2248次阅读
    <b class='flag-5'>深度</b><b class='flag-5'>学习</b>为什么还是无法处理边缘场景?

    C++:const 的空间,常量也能占内存?

    ] != BLACK)): return True return False c++语言5g.FsW.dgdfgsg.cnJIWWQc++语言 c++
    发表于 04-16 19:19

    volatile的修饰符

    volatile完全的重要性。 1)一个参数既可以是const还可以是volatile吗?解释为什么。 2); 一个指针可以是volatile 吗?解释为什么。 3); 下面的函数有什
    发表于 01-06 07:39

    C语言嵌入式系统编程注意事项-内存操作

    程序是非法的:   const int SIZE = 10;  char a[SIZE]; /* 非法:编译阶段不能用到变量 */  关键字volaTIle  C语言编译器会对用户
    发表于 01-04 07:31

    请问如何实现C语言访问MCU寄存器?

    单片机的特殊功能寄存器SFR,是SRAM地址已经确定的SRAM单元,在C语言环境下对其访问归纳起来有两种方法。 采用标准C的强制类型转换和指针来实现   采用标准C的强制转换和指针的概
    发表于 12-26 07:00

    关键字volatile的含意

    关键字volatile有什么含意? 一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心
    发表于 12-23 06:33

    如何深度学习机器视觉的应用场景

    深度学习视觉应用场景大全 工业制造领域 复杂缺陷检测:处理传统算法难以描述的非标准化缺陷模式 非标产品分类:对形状、颜色、纹理多变的产品进行智能分类 外观质量评估:基于学习的外观质量标准判定 精密
    的头像 发表于 11-27 10:19 391次阅读

    什么是‍‍volatile

    volatile是一个类型修饰符(type specifier)。 volatile的作用是作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值。 volatile变量是说这变量可能会被意想不到地改变,这样
    发表于 11-25 06:36

    C语言特性

    ,开发者们可以在这些社区中分享经验、交流技术、解决问题。在社区中,开发者们可以找到大量的开源项目、代码示例、技术文章等资源,为学习和使用 C 语言提供了有力的支持。当遇到技术难题时,在社区中提问往往能得到其他开发者的热心帮助,快
    发表于 11-24 07:01

    C语言和单片机C语言有什么差异

    单片机c语言相对于普通C语言增加了一些基本的指令,还有变量的赋值是16进制,当然单片机c语言只牵
    发表于 11-14 07:55

    一文了解Mojo编程语言

    Mojo 是一种由 Modular AI 公司开发的编程语言,旨在将 Python 的易用性与 C 语言的高性能相结合,特别适合人工智能(AI)、高性能计算(HPC)和系统级编程场景。以下是关于
    发表于 11-07 05:59

    自动驾驶中Transformer大模型会取代深度学习吗?

    [首发于智驾最前沿微信公众号]近年来,随着ChatGPT、Claude、文心一言等大语言模型在生成文本、对话交互等领域的惊艳表现,“Transformer架构是否正在取代传统深度学习”这一话题一直被
    的头像 发表于 08-13 09:15 4436次阅读
    自动驾驶中Transformer大模型会取代<b class='flag-5'>深度</b><b class='flag-5'>学习</b>吗?

    灵活高效双引擎驱动:ZBUFF让C语言内存操作更智能!

    高性能系统。 一、ZBUFF核心库常用函数 如果小伙伴们此前没有接触过C语言或者不精通C语言,把ZBUFF核心库当成新库来学习即可,建议先从
    的头像 发表于 08-11 13:27 763次阅读
    灵活高效双引擎驱动:ZBUFF让<b class='flag-5'>C</b><b class='flag-5'>语言</b>内存操作更智能!

    深度学习遇上嵌入式资源困境,特征空间如何破局?

    近年来,随着人工智能(AI)技术的迅猛发展,深度学习(Deep Learning)成为最热门的研究领域之一。在语音识别、图像识别、自然语言处理等领域,深度
    发表于 07-14 14:50 1337次阅读
    当<b class='flag-5'>深度</b><b class='flag-5'>学习</b>遇上嵌入式资源困境,特征空间如何破局?

    深度操作系统deepin 25全面支持凹语言

    近日,deepin(深度)社区宣布,deepin 25 现已完成对国产通用编程语言语言 (Wa-Lang) 的兼容性测试。在 deepin 25 默认安装环境下,即可直接使用凹语言
    的头像 发表于 07-10 15:26 1193次阅读
    <b class='flag-5'>深度</b>操作系统deepin 25全面支持凹<b class='flag-5'>语言</b>