【C深剖】详解static

简介: 【C深剖】详解static

前言

本节内容主要是围绕static关键字来展开的,重点阐述了static创建的意义,由来,使用…

1.static关键字修饰全局变量和函数

在介绍static关键字之前,我们首先来准备一下预备知识,同样这些预备知识也是比较关键的。

1.1多文件内容介绍

在同一个vs项目当中,有许多源文件(后缀为.c文件),其中多文件是指的便是多个.c文件(下图)。

那我来问大家几个问题,看看大家对多文件了解多少:

1.自定义函数是否可以直接被调用?可以!!!
2.全局变量是否可以被直接调用?不可以!!!

在main文件中,我并没有包含test的头文件但是却可以调用起来,下面来主要解释一下为什么会出现这种情况?

因为报错是在编译阶段完成的,编译器在编译函数阶段没有发现什么特别大的错误。

在我们写完代码的时候,编译器要对我们写的代码要进行编译链接,是分别对每个源文件进行处理的,其中在编译这一整个过程中,我们写的函数是以某种形式存在的,编译器并不会对其进行详细处理,发现找不到这么一个自定义函数时候,编译器顶多报个警告而已,实际上到了链接这个过程编译器才会把两个文件链接起来,发现在另一个文件中找到了这么一个函数定义,也就运行成功了。

但是我们的定义的全局变量在编译阶段就会被编译器辨认出没有定义,自然也就编译器给你终止程序了,也就不会运行起来。

为了解决这个问题,我们C语言中有一个专门用来声明的关键字:extern关键字

只要我们在我们需要声明的文件中extern一下这个变量或者函数,编译器便可以在编译期间就可以知道有这么个变量允许调用,也就不会报错了。

但是这里我需要强调一个细节,是这样的,有很多初学者会把声明写成这个样子:

extern int n = 100;

这种写法对吗?显然是错误的,至于为什么,这牵扯到了变量的声明的本质理解。

声明并没有开辟空间,但是赋值操作需要空间存放值。

在C语言深度解剖第一节内容我们说过,变量定义本质上是开辟空间,变量声明本质上是告知,两者最大的差距在于有没有空间被创建出来,extern是声明的关键字,但是在上面的写法中却要给n赋值,既然要赋值就得需要空间啊,但是声明是没有开辟空间的!

看下面图片,声明之后没有任何报错甚至是警告也没有:

但是有个问题哈,就是我们在做一个项目的时候,往往都会有几十个甚至是几百个这样的源文件,我们难道是每个源文件在调用其他文件的变量或者函数的时候都需要extern声明吗?这样做的很大问题就是,维护成本太高了!

1.2头文件

为了解决这个问题,C语言中有专门的文件来存放声明内容,这个文件称为:头文件(后缀为.h)

头文件有一个比较普遍的问题就是重复问题,重复包含头文件也就是多重复了几次,也不会报错其实,但是会重复拷贝头文件内容,造成效率降低。

下面给出一个解决方法:在头文件中包含#pragma once

头文件中的内容应该写什么?库头文件,自定义函数的声明,变量声明,宏定义等等…

注意:

1.(库文件一半用<库文件名称>这个符号来进行声明,自定义源文件名称用“源文件名称”双引号来进行声明) 约定俗成而已。

2.函数声明与变量声明都建议带上extern,虽然说函数声明可以不用带extern,毕竟不写声明都可以允许,同时函数声明与定义要保持一致。

有了上面的知识进行铺垫,下面来介绍static关键字哈。

1.3static函数+全局变量与函数

直接给结论:

static+全局变量(函数):static的全局变量只可以在本文件中使用,不再允许直接被引用到其他文件当中,改变的变量(函数)的作用域。但是这里需要注意的是static修饰的变量或者函数可以被间接访问

被static修饰的局部变量和函数虽然不可以被直接访问,但是可以被间接进行访问:(函数嵌套)

2.static关键字修饰局部变量

static关键字修饰局部变量,会改变局部变量的生命周期,让临时的生命周期延长为类似于全局变量的生命周期。

临时变量(局部变量)的生命周期大家可以看下面代码来进行体会一下:

//体会临时变量的生命周期
void my_print(void)
{
  int a = 1;
  printf("%d\n", a);
  a++;
}
int main()
{
  int i = 0;
  for (i = 0; i < 10; i++)
  {
    printf("it is the %d time:\n", i);
    my_print();
  }
  return 0;
}

这其实就是因为每次循环进入自定义函数的时候都是重新创建和销毁临时变量a,所以a的值始终是1…

但是,如果我给a加一个static进行修饰:

3.static关键字修饰的意义:

至于为什么C语言要造static关键字,其实我认为可以这样理解:

C程序是面向程序员的,最终是要造出一个比较大的项目来进行应用的,那这个比较大的项目就会涉及到很多的源文件,这就涉及到多文件,头文件等等,那么C程序运行时候,一定会进行一个数据交互,为了减少维护的成本,那么C设计者一定会允许变量函数跨文件进行访问,那么就再次验证的头文件的重要性,但是我想说如果所有文件都是互关的,那么对应的一些功能接口就会很多,那么意味着程序的暴露程度就会越高,那么代码的隐秘性就会越差,不利于代码的安全性;还有一点就是接口太多,用户的使用成本会比较高,为了解决上面说的两个问题,static关键字这种让变量程序文件隐藏起来的关键字应运而生。

相关文章
|
1月前
|
Java 程序员
Java 面试高频考点:static 和 final 深度剖析
本文介绍了 Java 中的 `static` 和 `final` 关键字。`static` 修饰的属性和方法属于类而非对象,所有实例共享;`final` 用于变量、方法和类,确保其不可修改或继承。两者结合可用于定义常量。文章通过具体示例详细解析了它们的用法和应用场景。
28 3
|
1月前
学习使用static的另一用法
学习使用static的另一用法。
46 12
|
1月前
|
Java
Java关键字 —— static 与 final 详细解释!一看就懂 有代码实例运行!
这篇文章详细解释了Java中static和final关键字的用法,包括它们修饰类、方法、变量和代码块时的行为,并通过代码示例展示了它们的具体应用。
180 0
Java关键字 —— static 与 final 详细解释!一看就懂 有代码实例运行!
|
3月前
|
存储 Java 对象存储
【Java基础面试四十三】、 static和final有什么区别?
由于网络原因,我无法获取到您提供的链接内容。如果需要我解析该网页,请确保链接有效并重试,或者提供其他问题,我会尽力帮助您。
|
3月前
|
编译器 C语言
【C深剖】三组典型C题+float在if中的比较
【C深剖】三组典型C题+float在if中的比较
|
6月前
|
存储 缓存 Java
从static说起
从static说起
42 0
|
存储 编译器 C语言
面试官:说一下你对const static volitale的理解 =_=
面试官:说一下你对const static volitale的理解 =_=
|
设计模式 存储 Java
static和final关键字 学习 demo练习
static和final关键字 学习 demo练习
65 2
|
存储 编译器 C语言
C语言中extern,static, register,volatile 关键字的作用;保姆级教学!
C语言中extern,static, register,volatile 关键字的作用;保姆级教学!
|
Java 编译器 C语言
【重学C/C++系列(八)】:如何理解C++中的void*?
首先void*中的void代表一个任意的数据类型,"星号"代表一个指针,所以其就是一个任意数据类型的指针。
【重学C/C++系列(八)】:如何理解C++中的void*?