C语言中关键字一次说清楚!!!

2023-11-15

目录

一. static

1. 作用

2. 一些例子帮助大家更深刻的理解static的几个作用

(1)修饰局部变量:

(2).修饰全局变量和函数

二. const

1. 作用:使得变量不允许被修改, 提高代码的健壮性。

2. 本质:给编译器看的, 在编译阶段起作用。

3. 常见考题:常量指针和指针常量

4. 一些例子

三. volatile

1. 先说作用

2. 编译器的过度优化指的又是什么呢?

3. 总结:


一. static

1. 作用

(1)修饰全局变量:它和普通全局变量没区别, 唯一的区别就是使用static修饰的全局变量无法被同一个工程中的其它源文件使用extern关键字访问, 限定了该全局变量的作用域在该文件中, 总结就是从整个工程都可以访问变成了定义该静态全局变量的源文件。

(2)修饰函数:和上述修饰全局变量的作用差不多, 使用static修饰的函数限定在了该模块内使用, 也可以说是定义该静态函数的源文件中。

(3)修饰局部变量:和普通的局部变量的属性差不多, 唯一的不同是它的生命周期从普通的函数调用开始到函数执行完结束, 变成了整个进程结束后它的生命周期才结束,简单来说就是普通的局部变量内存分配在栈区, 调用完自动销毁回收内存, 而使用static修饰的局部变量的内存是分配在全局区(数据段, 静态区),程序运行结束后才释放内存。

2. 一些例子帮助大家更深刻的理解static的几个作用

(1)修饰局部变量:

有这样一个例子, 我想实现一下输入整数输出字符串, 大家别看代码的实现, 就看static的使用场景就好, 别偏题了。

在下面这个实列中我们可以看到在函数itoa中定义了一个局部数组, 将输入的整数处理完之后, 我想返回数组的首地址, 并在主程序中打印它,运行后出现错误, 见图一。

#include <stdio.h>

char *itoa(int num);
int main(int argc, const char *argv[])
{
	int num;
	char *p;
	printf("please input your want convert digit:");

	scanf("%d", &num);
	p = itoa(num);

	puys(p);
	return 0;
}
char *itoa(int num) {
    char arr[128];     //大家注意看这里
	int i = 0, j, k;
	while(num) {
		j = num % 10;
		num = num / 10;
		arr[i] = j + '0'; 
		i++;
	}
	k = i - 1;
	i = 0;
	while(i < k) {
		j = arr[i];
		arr[i] = arr[k];
		arr[k] = j;
		i++;
		k--;
	}

	return arr;

}

图1

 这个时候我们就可以加上static关键字修饰一下数组arr, 使其变成函数体内部的全局变量, 延长生命周期,让主函数拿到它的地址。

static char arr[128];     //大家注意看这里

(2).修饰全局变量和函数

我们写出三个文件, 1.c, 2.c, main.模拟在过程中不同的模块。

/*a.c*/
int a = 10;
/*b.c*/
static int a = 100;
/*main.c*/

#include <stdio.h>

exterm int a;
int main(int argc, char *argv[])
{
    printf("a = %d\n", a);

    return 0;
}

请问大家, 主函数中访问到的a的值是多少?

答案:访问到的值是a.c中没有用static关键字修饰的a, 作用假设我们是一个小组, 每个人负责写不同的函数模块, 不能确保每个人定义的全局变量的变量名都不同对吧, 所以往这个例子上想static修饰全局变量的作用就是防止全局变量重名的问题, 造成编译器不知道访问哪一个, 出现链接错误。

static修饰函数也是类似的作用。

二. const

1. 作用:使得变量不允许被修改, 提高代码的健壮性。

2. 本质:给编译器看的, 在编译阶段起作用。

3. 常见考题:常量指针和指针常量

*p指向变量的值不能修改, 错误:(*p)++

p的地址不能被修改             错误:p++

*p和p的地址都不能被修改   错误:任意一种都是错误的写法

4. 一些例子

区分别的函数拿到我这个变量是进行读还是写操作, 以此判断要不要加上const关键字修饰。

如果只是读操作,建议加上const。

三. volatile

1. 先说作用

防止编译器的过度优化, 不去缓存器里取值, 都是去取真实地址里面的值

使用场景:

i.访问特殊功能寄存器

ii.线程间共享的全局变量

iii.任务与中断共享的全局变量

2. 编译器的过度优化指的又是什么呢?

假设我写出这样的代码:

int a = 10;
int b = a;
int c = a;

 在arm里代码的执行逻辑是这样的, 先取出变量a中的值到cpu的缓存器中, 在把缓存器中的值赋值给b, 我们写的代码是不是又想取出a的值给c, 那是不是又要重复a赋值给b的流程先取出a的值到缓存器中再赋值给c, 这样效率就有点小低了。

3. 总结:

所以编译器的优化就是这一步, 它分析出我们的代码没有修改真实地址a的值和缓存器中的值, 那么它就直接把缓存器中的值给变量c了。

这样来看这样做是好事, 但请大家记住一下三种情况对于我们来说就不是好事了, 因为变量a的值, 也就是真实地址中的值在一下三种情况中会出现被修改的情况, 这样的话, 变量c拿到的值就不是a的真实值, 而是没有被修改之前缓存器中的值。

i.访问特殊功能寄存器

ii.线程间共享的全局变量

iii.任务与中断共享的全局变量

各位看官切记切记, 不然当项目因为这种问题出现bug的时候是无法发现, 无法调式的。

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

C语言中关键字一次说清楚!!! 的相关文章

随机推荐

  • Hive 一文读懂

    Hive 简介 1 1 什么是Hive 1 hive简介 Hive 由Facebook开源用于解决海量结构化日志的数据统计 Hive是基于Hadoop的一个数据仓库工具 可以将结构化的数据文件映射为一张表 并提供类SQL查询功能 2 Hiv
  • opencv边缘检测-拉普拉斯算子

    sobel算子一文说了 索贝尔算子是模拟一阶求导 导数越大的地方说明变换越剧烈 越有可能是边缘 那如果继续对f t 求导呢 可以发现 边缘处 的二阶导数 0 我们可以利用这一特性去寻找图像的边缘 注意有一个问题 二阶求导为0的位置也可能是无
  • python报错AttributeError module ‘scipy.misc‘ has no attribute ‘imresize‘和 ‘imread‘

    python报错AttributeError module scipy misc has no attribute imresize 和 imread 报错原因 scipy版本过高 解决方案 降低scipy版本 如下 pip install
  • 迁移学习之resnet50——解决过拟合及验证集上准确率上不去问题

    keras之resnet50迁移学习做分类 问题1描述 迁移学习用resnet50做分类 验证集上的准确率一直是一个大问题 有时候稳定在一个低的准确率 我的一次是一直在75 上下波动 问题2描述 resnet50迁移学习 训练集上的准确率一
  • IDEA使用jsp可以访问页面,转换为html弹出页面为404

    这种办法为绕过controller直接访问静态页面 大家只要路径对 在springmvc xml中配置好一个 标签即可
  • 【mysql】mysql 常用建表语句

    1 建立员工档案表 要求字段 员工员工编号 员工姓名 性别 工资 email 入职时间 部门 2 合理选择数据类型及字段修饰符 要求有NOT NULL auto increment primary key等 make by kakane D
  • arcgis10.2破解版下载及其详细教程;;;附带10.1-10.6的破解版,没有教程

    1 arcgis10 2破解版 https blog csdn net bigemap article details 81131840 2 arcgis10 1 10 5破解版安装包 https blog csdn net e wsq a
  • 【c++】8.map和vector容器查找、删除指定元素、emplace、insert

    1 查找与删除 vector 和 map 容器中指定元素 vector 查找或删除vector的指定元素 123 方法1 使用迭代器 不同于map map有find方法 vector本身没有find这一方法 std vector
  • 从浅到深理解bert

    更多查看https github com B C WANG AI Storage 4 2 4 2从浅到深理解bert 4 2 1 理解Attention 参考https www cnblogs com robert dlut p 86382
  • Pytorch save_image和make_grid函数详解

    Pytorch save image和make grid函数详解 make grid用于把几个图像按照网格排列的方式绘制出来 save image用于保存图像 这两个函数的函数签名差不多 所以只说一个 def make grid tenso
  • excel python插件_再见 VBA!神器工具统一 Excel 和 Python

    大家好 我是东哥 经常给大家推荐好用的数据分析工具 也收到了铁子们的各种好评 这次也不例外 我要再推荐一个 而且是个爆款神器 Excel和Jupyter Notebok都是我每天必用的工具 而且两个工具经常协同工作 一直以来工作效率也还算不
  • 线段树模板

    线段树属于高级数据结构 本文粗略地讲解了一下线段树的模板 大家直接拿去用就好 long long ls int x return x lt lt 1 long long rs int x return x lt lt 1 1 const i
  • 电感选型计算

    转载 https www richtek com Design 20Support Technical 20Document AN053 电感之种类与其特性分析 摘要 电感器是开关转换器中非常重要的元器件 如用于储能及功率滤波器 电感器的种
  • react render中进行if判断

    在render中进行if条件判断然后加载相应的模块进行渲染方法如下 第一种 第二种
  • Spark的DataFrame和Schema详解和实战案例Demo

    1 概念介绍 Spark是一个分布式计算框架 用于处理大规模数据处理任务 在Spark中 DataFrame是一种分布式的数据集合 类似于关系型数据库中的表格 DataFrame提供了一种更高级别的抽象 允许用户以声明式的方式处理数据 而不
  • 【数据分析之道-NumPy(四)】numpy广播机制

    文章目录 专栏导读 1 广播机制 2 一维数组和二维数组的广播 3 二维数组和三维数组的广播 4 标量和数组的广播 5 形状不兼容的数组不能进行广播 专栏导读 作者简介 i阿极 CSDN Python领域新星创作者 专注于分享python领
  • 小游戏:红色警戒争霸战!

    这个是当年自己在学校里面写的小游戏 现在看看好弱智啊 第一代的代码 public struct Heros public string name public double hp public double mp public double
  • a标签下载pdf文档

    开发过程中 有时我们需要点击a标签然后可以下载pdf文档 但是结果经常是pdf文档直接就在浏览器中打开了 那么想要直接下载需要怎么实现呢 实现方式 在a标签的href中写上要下载的pdf文档的地址 加上download下载属性 最后记得让后
  • Tencent://Message/协议的实现原理 .

    Tencent Message 协议的实现原理 2008年07月17日 星期四 12 04 腾讯官方通过 Tencent Message 协议可以让QQ用户显示QQ TM的在线状态发布在互联网上 并且点击 不用加好友也可以聊天 官方链接 h
  • C语言中关键字一次说清楚!!!

    目录 一 static 1 作用 2 一些例子帮助大家更深刻的理解static的几个作用 1 修饰局部变量 2 修饰全局变量和函数 二 const 1 作用 使得变量不允许被修改 提高代码的健壮性 2 本质 给编译器看的 在编译阶段起作用