嵌入式养成计划-9-存储类型、变量修饰词、宏

十九、存储类型

  • 存储类型:auto(自动)、static(静态)、extern(外部)、register(寄存器)
  • 修饰词:const(不允许被修改)、volatile(防止内存被编译器优化)

19.1 auto

作用:声明自动类型,当局部变量省略存储类型时,是自动类型
  1. auto不可以修饰全局变量
  2. 函数只能使用 static / extern 进行修饰,不可以使用 auto 修饰
  3. auto修饰的变量内存在栈区

19.2 static

作用:声明静态类型,延长生命周期。

static关键字修饰:

  • 全局变量:当static用于修饰全局变量时,它使得该变量的作用域限制在当前文件内,即使其他文件声明了同名的全局变量,它们也不会相互影响。
  • 局部变量:当static用于修饰局部变量时,它使得该变量的生命周期延长,即变量在程序执行期间保持其值,而不是在每次函数调用时重新初始化。这在递归函数中特别有用,不能跨过作用域使用。
  • 指针:static修饰指针本身并没有特殊意义,它与普通指针的行为没有区别。但是,如果将static用于指针指向的变量,那么该变量的生命周期将会延长,类似于上述局部变量的效果。static修饰的指针不可以指向自动类型的变量地址。
  • 函数:当static用于修饰函数时,它将使函数的作用域限制在当前文件内,其他文件无法访问该函数,起到了函数的私有化效果。
  • 线程局部变量(Thread-local variables):
    C11标准引入了线程局部变量的概念,通过static关键字与关键字_Thread_local一起使用,可以在多线程程序中创建独立于线程的局部变量。每个线程都拥有其独立的变量实例,互不干扰。

代码示例:

  • 1.static修饰全局变量
全局变量省略存储类型,默认是extern存储类型,全局变量的内存空间在静态区。
一般全局变量不会使用static修饰,原因是全局变量省略存储类型,内存已经在静态区.

在这里插入图片描述

  • 2.static修饰局部变量
作用:static修饰局部变量,延长生命周期,不是作用域、
	生命周期	:	内存空间的神情,到释放
	作用域	:	在程序的有效范围

在这里插入图片描述

  • 3.static修饰函数
作用:static修饰函数,使函数声明周期在本文件有效,不可以跨文件调用
	函数省略存储类型,默认是extern存储类型

在这里插入图片描述

  • 4.static修饰指针
static修饰的指针不可以指向自动类型的变量地址
原因	:	自动类型的变量地址后分配,在编译阶段分配空间
		静态类型的变量地址先分配, 在项目启动时就分配空间

在这里插入图片描述

19.3 extern

作用:声明外部存储

extern关键字声明:

  • 全局变量:当在一个文件中使用extern修饰全局变量时,表明该变量是在其他文件中定义的全局变量。这样可以在当前文件中使用其他文件定义的全局变量,从而实现多文件共享全局变量的目的。
  • 局部变量:extern不应用于局部变量,因为局部变量的作用域仅限于定义它的代码块内,无需在其他文件中访问。
  • 指针:extern同样也可以用于指针,但是它的效果与全局变量的情况类似,表示该指针是在其他文件中定义的。
  • 函数:extern不应用于函数,因为函数的作用域是全局的,无需通过extern来在其他文件中访问。
  1. 当前全局变量省略存储类型,默认是extern
  2. 当前全局变量省略存储类型,默认是extern
  3. extern修饰的变量,存储在静态区
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

总结:

  • static主要用于限制作用域和延长生命周期。
  • extern主要用于在多文件项目中共享全局变量。

19.4 register

作用:声明寄存器变量,
	寄存器类型的变量,访问速度快,但不可以取地址

存储器等级:寄存器 > 高速缓冲存储器cache > 主存 > 辅存

在这里插入图片描述

19.5 const

作用:修饰的值不发生改变
	 1. const修饰的全局变量,内存在静态区的只读段,只读不可以修改
	 2. const修饰的局部变量,内存在栈区,不可以修改
	 3. const和指针结合:
	 
	 	const int *p;  *在const的右边,const修饰的值,值不可以改变,地址可以改变
		int const *p;*在const的右边,const修饰的值,值不可以改变,地址可以改变
		int * const p;*在const的左边,const修饰的地址,不地址可以改变,值可以改变
		const int * const p;第一个const修饰的是指,第二个const修饰的地址,值和地址均不可以改变
		int const * const p; 第一个const修饰的是指,第二个const修饰的地址,值和地址均不可以改变	 

在这里插入图片描述

19.6 volatile

作用:防止内存优化,保存内存可见性

在C/C++中,volatile是一个关键字,用于告诉编译器该变量可能在程序执行过程中被意外地更改,从而防止编译器对该变量进行优化,以确保程序的正确性。volatile的主要用途是在以下情况下:

  1. 防止编译器优化
    编译器在优化代码时会尽可能地减少对变量的读取和写入,以提高程序的执行效率。但是,有些变量的值可能不是由当前代码段控制的,而是由硬件或其他并发线程改变的。使用volatile关键字可以告诉编译器不要对该变量进行优化,而是每次都从内存中读取其最新值。

  2. 与中断处理相关
    在嵌入式系统和多线程环境中,中断可能会修改程序中的变量。如果这些变量没有被声明为volatile,编译器可能会优化掉对这些变量的读取操作,导致程序出现错误。

  3. 与外设交互
    在嵌入式系统中,与外设进行交互时,使用volatile关键字可以确保对外设寄存器的访问不被优化,从而确保与外设的正确通信。

请注意:volatile关键字只是告诉编译器该变量可能在任意时刻被修改,但它并不能解决所有多线程并发访问的问题。对于多线程并发的情况,更复杂的同步机制(如互斥锁)通常需要使用。在多线程环境中,volatile关键字仅仅是一个保证该变量不被优化的手段,而并不能保证线程安全。

二十、宏

宏		:	一旦定义不可以修改
定义格式	:	#define   宏名  宏体
	宏制作替换、不做计算、不做正确性检查
	宏不属于C语句,所以不加分号

20.1 宏定义

#define M 100
#define PAI 3.14
#define CH 'A'
#define STRING "hello"
#define N
#define G =100
//	上面这些都是宏
int main(int argc, const char *argv[])
{
    printf("M=%d\n",M);
    printf("PAI=%f\n",PAI);
    printf("CH=%c\n",CH);
    printf("STRING=%s\n",STRING);
//    N=6;  //一旦宏定义没有赋值,那么后期就不可以赋值
    printf("N=%d\n",N);
//    printf("G=%d\n",M);

    return 0;
}

20.2 宏函数

20.2.1 自定义宏函数

定义格式	:	#define  宏函数名(参数列表)  宏体
#define	:	定义宏的标志,不可以省略
宏函数名	:	满足命名规范,一般大写
参数列表	:	不加数据类型
宏体		:	实现的程序,不加{}

代码示例:

1> 带括号的宏函数
#define SUM(x,y) x+y

#define SUM1(x,y) (x+y)

#define MIN(x,y) x>y?y:x
int main(int argc, const char *argv[])
{

#if N
    int a=10,b=100;
    printf("和=%d\n",SUM(a,b)/2);//x+y/2=60

    printf("和=%d\n",SUM1(a,b)/2);//(10+100)/2=55
    printf("%d",MIN(a,b));
#endif

20.2.2 系统宏函数

#if 宏名
    C语句1;
#else
    C语句2;
#endif
当宏名条件为真,则执行C语句1,否则执行C语句2
#if 0作用注释

#ifdef 宏名
    C语句1;
#else
    C语句2;
#endif
当宏名已经定义了,则执行C语句1,否则执行那个C语句2

#ifndef 宏名
    C语句1;
#else
    C语句2;
#endif
当宏名没有定义,则执行那个C语句1,否则执行那个C语句2;

#undef 宏名: 取消宏

思维导图

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

zhk___

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

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

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

打赏作者

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

抵扣说明:

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

余额充值