单片机/C/C++八股:(三十一)static 关键字的作用

上一篇下一篇

static 关键字的作用?

static:[adj] 静态的

总结在最后面! 可直接看

static 变量称为静态存储类型的变量,所谓静态就是变量在程序运行期间一直存在。

static 变量的特点如下:

  • 在内存中以固定地址存放,而不是以堆栈方式存放(程序运行多次之后,依然存放在同一地址);
    • 存在 .bss(未初始化或初始化为0)或 .data(已初始化为非0值)段,不在栈上
  • 只要程序没结束,此变量就不会消失,即使放在子函数中被反复调用,每次调用的时候,都会保留调用结束的值;
  • static 修饰的全局变量/函数,其他文件无法使用(其他文件即使使用 extern 声明,也无法访问该变量);
  • 如果没有初始化,那么静态变量的初始值默认是 0 。

举例,有如下程序:

#include <stdio.h>
void fun() 
{
	int a=10;
	a++;
	printf("%d %p\n",a,&a);
}

int main()
{
	int i=0;
    while(i<5)
    {
    	fun();
    	i++;
    }
    return 0;
}

程序运行之后的结果为(运行两次):

/* 第一次运行结果 */
11 00000063867ff90c
11 00000063867ff90c
11 00000063867ff90c
11 00000063867ff90c
11 00000063867ff90c
    
/* 第二次运行结果 */
11 0000002554dff7dc
11 0000002554dff7dc
11 0000002554dff7dc
11 0000002554dff7dc
11 0000002554dff7dc
    
// 两次运行,分配的地址都是不确定的

现在将变量 a 定义为静态变量,并且不初始化:

#include <stdio.h>
void fun() 
{
	static int a;
	a++;
	printf("%d %p\n",a,&a);
}

int main()
{
	int i=0;
    while(i<5)
    {
    	fun();
    	i++;
    }
    return 0;
}

程序运行之后的结果为(运行两次):

/* 第一次运行结果 */
1 00007ff74fb4a000
2 00007ff74fb4a000
3 00007ff74fb4a000
4 00007ff74fb4a000
5 00007ff74fb4a000
    
/* 第二次运行结果 */
1 00007ff74fb4a000
2 00007ff74fb4a000
3 00007ff74fb4a000
4 00007ff74fb4a000
5 00007ff74fb4a000
    
// 两次运行,分配的地址都是固定的,并且初始值为 0 (+1后才打印)

【总结】

static 关键字有三种用法:

  1. 定义静态局部变量:使其生命周期延长到程序结束,值会随着每次调用而改变
    • 存放地址:未初始化或显示初始化为0存在 .bss段,初始化为非0值则存在 .data 段,不在栈上。
  2. 定义静态全局变量:限制作用域,别的文件不可调用,即使同一模块的 .c 和 .h 文件之间用 extern 也不行(如key.c/key.h);
    • 存放地址:未初始化或显示初始化为0存在 .bss段,初始化为非0值则存在 .data 段,不在栈上。
  3. 定义静态函数:限制函数作用域,别的文件不可调用,即使同一模块的 .c 和 .h 文件之间用 extern 也不行(如key.c/key.h);
    • 和普通函数一样存放在代码段(.text)中。
// 1. 静态局部变量
static int count = 0;

// 2. 静态全局变量
static int globalVar;

// 3. 静态函数
static void localFunc(void) {}

【注意】:

  • 在 C 中,结构体成员不可使用 static 定义(C++ 中可以)!但结构体本身可以用 static 定义

    • 解释:在C中成员只是结构体布局的一部分,无独立存储;而 static 是存储类说明符,只适用于变量和函数,不能用于成员。

    • 举例:

      // 不可以:成员不能是 static
      struct S {
          static int x;   // 编译错误
      };
      
      // 可以:结构体变量可以是 static
      static struct S obj;
      
  • 在 C 中,static 定义的变量,必须使用 “编译时常量表达式” 进行初始化(例如数字、字符、字符串字面量、NULLsizeof 表达式、取静态/全局变量的地址等编译时就能确定的值)

    • 解释:因为静态变量和全局变量在程序启动时(main 执行前)就已经分配好内存并完成初始化,此时整个运行时环境(堆栈、函数调度等)尚未就绪,无法执行任何需要 CPU 运行的代码。

    • 错误行为举例:

    // 严重错误
    int main() {         
      static int *p = malloc(sizeof(int)); 
      *p = 20;
    
      free(p);
      p=NULL;
      return 0;
    }
    
    // 正确
    int main() {
      static int *p = NULL;   		// p存放在.bss段       
      if (p == NULL) {
          p = malloc(sizeof(int));	// 运行时赋值,完全合法
      }
      *p = 20;
    
      free(p);
      p=NULL;
      return 0;
    }
    

    不过一般不会用 static 来定义用于 malloc 的指针,纯属突发奇想😄。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值