前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >static const volatile __weak关键字解析

static const volatile __weak关键字解析

作者头像
wenzid
发布2021-03-04 15:36:28
2950
发布2021-03-04 15:36:28
举报
文章被收录于专栏:wenzi嵌入式软件wenzi嵌入式软件

这篇文章较为基础,笔者在这里写下来作为对以前知识的一个回顾

static

对于 static 关键字来讲,它既可以用来修饰变量同时也可以用来修饰函数,而变量从大的方向上来讲又分为局部变量和全局变量,static 对于这两种变量的修饰也具有不同的意义。

修饰变量

静态全局变量:使用 static 修饰全局变量之后,其作用域仅仅限于被定义的文件中,其他文件即使使用 extern 声明也没有办法使用它。更加准确地说法应该是作用域从定义之处开始,到文件结尾处结束,在定义之处前面的那些代码也不能够使用。

静态局部变量:由于是在函数体内定义的,所以就只能够在这个函数里使用,但是由于由 static 修饰的变量总是处在内存的静态区,所以即使这个函数运行结束,这个变量也不会销毁。

修饰函数

使用 static 修饰的函数,并不是指函数的存储方式,而是说对于这个函数的作用域仅仅限于本文本,又被称之为内部函数。使用内部函数的好处是,不同人编写不同的函数时,不用担心自己的函数是否会与其他文件的函数重名。

const

const 修饰的变量被称之为只读变量,其值在编译时不能够被使用,因为编译器在编译时不知道其中存储的内容。

修饰一般变量和数组

使用 const 修饰一些一般的变量或者是数组时可以采用如下的方式:

代码语言:javascript
复制
int const i = 2;
const int i = 2;

虽然上述的写法不一样,但是其意义是完全一致的,那么修饰数组也可以采用上述方式:

代码语言:javascript
复制
int const a[5] = {1,2,3,4,5};
const int a[5] = {1,2,3,4,5};

上述两句代码的意义也是完全一致的。

修饰指针

在修饰指针的时候,有如下四种方式:

代码语言:javascript
复制
const int *ptr;/*ptr可变,ptr指向的对象不可变*/
int const *ptr;/*意义与上述一致*/
int *const ptr;/*ptr不可变,ptr指向的对象可变*/
const int *const ptr;/*ptr和ptr指向的对象均不可变*/

笔者最开始看到这四条语句的时候,头很昏,老是记不清楚谁是谁,直到我在 C 语言深度剖析中看到的关于分辨这个的方法之后,就明白了很多。在书中是这样说的,const 最靠近谁,那修饰的就是谁,比如第一条代码,const 最靠近的是 *ptr ,那就是指向的对象不可变,第三条代码,const 最靠近的是 ptr ,那么就是 ptr 不可变。

修饰函数参数

const 也可以用于修饰函数参数,最为直观的一个例子是如果函数参数采用“指针传递”的方式,那么加入 const 参数可以防止意外地改动该指针,起到保护作用,比如如下字符串拷贝的一个函数原型:

代码语言:javascript
复制
void StrCopy(char *strDest,const char *strSrc);

此时如果函数内部试图改变 *strSrc 的内容,编译器将指出错误。

volatile

volatile 本意为“易变的”,它的作用是,当程序以一种编译器不知道的方式更改变量时,防止编译器对其进行任何优化。一个在嵌入式程序中很常见的例子就是中断的发生。比如如下例子:

代码语言:javascript
复制
char flag = 0;

int main(void)
{
    ...
    while(1)
    {
        if (flag)
            do_something();     
    }
}

/*中断服务程序*/
void ISR_1(void)
{
    flag = 1;
}

上述程序存在的一个问题就是 flag 没有使用 volatile 进行修饰,而编译器判断在 main 函数里没有别的操作对 flag 的值进行更改,可能就只执行一次从 flag 到某寄存器的读取操作,这时中断里对 flag 的操作将被忽略,函数将一直执行不到 do_something 的内容。用 volatile 将可以避免这个问题的出现。

__weak

weak的字面意思就是“微弱”的意思,其主要作用就是可以重新定义重名函数或变量而编译器不报错。笔者最开始注意到这个关键字是在使用 STM32 HAL 库的时候注意到的,比如如下这张图片所示:

图片右边的红色错误提示请忽略,因为没有当前所用 vim 编辑器没有设置当前工程的一部分头文件路径,所以报错

在上图我们可以看到左边的 HALMspInit 函数前面用 _weak 进行修饰,而图片右边又定义了 HALMspInit 函数,这时整个工程就定义了两个 HALMspInit 函数,声明可以有多个,但是定义只能存在一个,因为 _weak 的存在,所以不会报错,并且真正起作用的函数是没有用 _weak 修饰的函数。

总结

合理地使用关键字修饰函数或者变量,能够帮助我们写出更加稳定和更加健壮的代码,应该充分理解每个关键字具体的含义。

您的阅读是对我最大的鼓励,您的建议是对我最大的提升,欢迎点击下方图片进入小程序进行评论

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-04-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 wenzi嵌入式软件 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • static
    • 修饰变量
      • 修饰函数
      • const
        • 修饰一般变量和数组
          • 修饰指针
            • 修饰函数参数
            • volatile
            • __weak
            • 总结
            相关产品与服务
            云开发 CloudBase
            云开发(Tencent CloudBase,TCB)是腾讯云提供的云原生一体化开发环境和工具平台,为200万+企业和开发者提供高可用、自动弹性扩缩的后端云服务,可用于云端一体化开发多种端应用(小程序、公众号、Web 应用等),避免了应用开发过程中繁琐的服务器搭建及运维,开发者可以专注于业务逻辑的实现,开发门槛更低,效率更高。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档