【基础知识】C/C++关键字:auto,static,extern,register,volatile,explicit

参考自:https://blog.csdn.net/qq_38677814/article/details/79368632,仅作学习记录。

在我们的内存中,会分为三块:静态区,堆区,栈区。

  • 外部变量和全局变量存放在静态区,
  • 局部变量存放在栈区,
  • 动态开辟的内存存在堆区。

auto

auto类型:其实在函数中的局部变量,不加特殊声明,都是auto变量,但是关键字”auto”可以被省略。这些变量在函数被调用时分配存储方式,函数调用结束后这些存储空间就被释放了。

C语言中隐含的存储类型是 auto

static

补充阅读

总结:限制函数或变量的作用域,别的函数或cpp调用不了,且变量调用结束不消失。

static类型: 静态类型数据,数据存放在全局数据区,但作用域只是本文件/函数 中,所以你可以在两个不同的文件/函数内部申明同名的static变量,但是它们是两个不同的全局变量

两个注意点:

  • ①如果是定义在函数内,那么函数外不能对其访问。
  • ②如果是定义在函数外,那么该对象具有内部链接,其它程序文件不能对其访问

函数调用结束后,这些变量不消失,而保留当前数据,下一次调用时变量的值为上一次调用完成后的值。

extern

总结:放大函数或变量的作用域,别的cpp也能用。
函数在.h头文件里的声明默认是extern类型的,不用显示去写

详见此篇博客

外部变量声明,是指这是一个已在别的地方定义过的对象,这里只是对变量的一次重复引用,不会产生新的变量。

这在复杂的大型工程中会用到,比如我在我的程序中需要用到小明写的程序中的变量a,那么我在自己的程序中声明 extern int a; 告诉编译器这是别人模块中的变量,我拿过来用一下。

extern的原理很简单,就是告诉编译器:“你现在编译的文件中,有一个标识符虽然没有在本文件中定义,但是它是在别的文件中定义的全局变量,你要放行!

register

Register修饰符暗示编译程序相应的变量将将被频繁使用,如果可能的话,应将其保存在CPU的寄存器中,以指加快其存取速度。但是,使用register修饰符有几点限制:

  • (1)只有局部自动变量和形式参数可以作为寄存器变量,其他(如全局变量)不行。
  • (2)CPU的寄存器数目有限,因此,即使定义了寄存器变量,编译器可能并不真正为其分配寄存器,而是将其当做普通的auto变量来对待,为其分配栈内存。当然,有些优秀的编译器,能自动识别使用频繁的变量,如循环控制变量等,在有可用的寄存器时,即使没有使用 register 关键字,也自动为其分配寄存器,无须由程序员来指定。
  • (3)局部静态变量不能定义为寄存器变量。因为一个变量只能声明为一种存储类别。

其实这个变量已经过时,因为现在的计算机处理速度够快,所以很少使用
在这里插入图片描述

volatile

参考博客

volatile提醒编译器它后面所定义的变量随时都有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据如果没有volatile关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值,如果这个变量由别的程序更新了的话,将出现不一致的现象

volatile的本意是“易变的”,由于访问寄存器的速度要快过RAM,所以编译器一般都会作减少存取外部RAM的优化。比如:
在这里插入图片描述
程序的本意是希望ISR_2中断产生时,在main当中调用do_something函数,但是,由于编译器判断在main函数里面没有修改过i,因此可能只执行一次对从i到某寄存器的读操作,然后每次if判断都只使用这个寄存器里面的“i副本”,导致do_something永远也不会被调用。

如果变量加上volatile修饰,则编译器保证对此变量的读写操作都不会被优化(肯定执行)。此例中i也应该如此说明。

一般说来,volatile用在如下的几个地方:

  • 1、中断服务程序中修改的供其它程序检测的变量需要加volatile;
  • 2、多任务环境下各任务间共享的标志应该加volatile;
  • 3、存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能由不同意义;
  • 另外,以上这几种情况经常还要同时考虑数据的完整性(相互关联的几个标志读了一半被打断了重写),在1中可以通过关中断来实现,2中可以禁止任务调度,3中则只能依靠硬件的良好设计了。

explicit

C++提供了关键字explicit,声明为explicit的构造函数不能在隐式转换中使用

1)C++的类型转换分为两种,一种为隐式转换,另一种为显式转换

2)C++中应该尽量不要使用转换,尽量使用显式转换来代替隐式转换

  • 隐式转换是系统跟据程序的需要而自动转换的。
//1)算术表达式
int m = 10;
double n = m;//n = 10.0;隐式把m转为double类型

int m = 10;
float f = 10.0;
double d = m + f;//n = 20.0;隐式把m和f转为double类型

//2)赋值
int *p = NULL; //NULL(0)隐式转换为int*类型的空指针值

//3)函数入参
float add(float f);  
add(2); //2隐式转换为float类型

//4)函数返回值
double minus(int a, int b) 
{  
    return a - b; //返回值隐式转换为double类型
}

//————————————————————————————————————————————————————————————————

void fun(CTest test); 

class CTest 
{ 
public: 
    CTest(int m = 0); 
} 
fun(20);//隐式转换
  • 显式转换也叫强制转换,是自己主动让这个类型转换成别的类型。
int m = 5;
char c = (char)m;//显式把m转为char类型

double d = 2.0;
int i = 1;
i += static_cast<int>(d);//显式把d转换为int类型

//————————————————————————————————————————————————————————————————

void fun(CTest test); 

class CTest 
{ 
public: 
    explicit CTest(int m = 0); 
} 
fun(20);//error 隐式转换
fun(static_cast<CTest>(20)); //ok 显式转换
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值