static、extern、register 和 const 关键字的使用

参考:朱老师带你零基础学Linux

一、静态局部变量(static)

静态局部变量定义时前面加 static 关键字

总结:

1、静态局部变量和普通局部变量不同

静态局部变量也是定义在函数内部的,但定义时前面要加 static 关键字来标识,静态局部变量所在的函数在调用多次时,只有第一次才经历变量定义和初始化

以后多次在调用时,不再定义和初始化,而是维持之前上一次调用时执行后这个这个变量的值,本次接着来用


2、静态局部变量在第一次函数被调用时创造并初始化,但在函数退出时它不死亡,而是保持其值等待下一次被调用

下次调用时不再重新创造和初始化该变量,而是直接用上一次留下的值为基础来进行操作


3、静态局部变量的这种特性,和全局变量非常类似,它们的相同点是都创造和初始化一次,以后调用时值保持上次不变

不同点在于作用域不同


二、register 关键字

register(寄存器),C 语言的一个关键字

register int i = 3;


总结:register 类型的局部变量表现上和 auto 是一样的,这东西基本没用,直到就可以了

register 被称为:C 语言中最快的变量,C 语言的运行时环境承诺,会尽量将 register 类型的变量放到寄存器中去运行(普通的变量是在内存中)

所以 register 类型的变量访问速度会快很多

但是它是有限制的:首先寄存器数目是有限的,所以 register 类型的变量不能太多,其次 register 类型变量在数据类型上有限制

譬如你就不能定义 double 类型的 register 变量

一般只在内核或者启动代码中,需要反复使用同一变量这种情况下才会使用


三、多文件 C 语言项目

1、简单的 C 语言程序(项目)只有一个 C 文件,编译的时候 gcc a.c -o a,执行的时候 ./a

2、复杂的 C 语言程序(项目)是由多个 C 文件构成的,譬如一个项目中包含 2 个 C 文件(a.c,b.c)

编译的时候 gcc a.c b.c -0 ab,执行的时候 ./ab


实验:

在 a.c 和 b.c 中分别定义 main 函数,各自单独编译时没问题;但是两个文件作为一个项目来编译 gcc a.c b.c -o ab 的时候,就会报错 multiple definition of 'main'

因为 a.c 和 b.c 这时候组成了一个程序,而一个程序必须有且只能有一个 main 函数


3、为什么需要多文件项目?为什么不在一个 .c 文件中写完所有的功能?

因为一个真正的 C 语言项目是很复杂的,包含很多个函数,写在一个文件中不利于查找、组织、识别

所以人为的将复杂项目中的很多函数,分成一个一个的功能模块,然后分开放在不同的 .c 文件中,于是乎有了多文件项目

所以,在 b.c 中定义的一个函数,很可能 a.c 中就会需要调用

你在任何一个文件中定义的任何一个函数,都有可能被其它任何一个文件中的函数来调用

但是大家最终都是被 main 函数调用的,有可能是直接调用,也可能是间接调用


4、多文件项目中,跨文件调用函数

在调用函数前,要先声明该被调函数的原型,只要在调用前声明了该函数,那么调用时就好像这个函数是定义在本文件中的函数一样


5、跨文件的变量引用

(1)在 a.c 中定义的全局变量,在 a.c 中可以使用,在 b.c 中不可以直接使用

(2)想在 b.c 中使用 a.c 中定义的全局变量,有一个间接的使用方式

在 a.c 中写一个函数,然后函数中使用 a.c 中定义的该全局变量,然后在 b.c 中先声明函数,再使用函数

即可达到在 b.c 中间接引用 a.c 中变量的目的

(3)想在 b.c 中直接引用 a.c 中定义的全局变量 g_a,则必须在 b.c 中引用前先声明 g_a,如何声明变量?

extern int g_a;


extern 关键字:

extern int g_a;  这句话是一个全局变量 g_a 的声明,这句话告诉编译器,我在外部(程序中不是本文件的另一个文件)某个地方定义了一个全局变量 int g_a

而且我现在要在这里引用它,告诉你编译器一声,不用报错了


四、const 关键字

const int i = 14;

const 和指针结合,共有 4 种形式

const int *p;            :p 是一个指针,指针指向一个 int 型数据。p 所指向的是常量

int const *p;            :p 是一个指针,指针指向一个 int 型数据。p 所指向的是常量

int *const p;            :p 是一个指针,指针指向一个 int 型数据。p 本身是常量,p 所指向的是变量

const int *const p; :p 是一个指针,指针指向一个 int 型数据。p 本身是常量,所指向的也是常量


结论和记忆的方法:

1、const 在 * 的前面表示 const 作用于 p 所指向的量。所以这个时候 p 所指向的是个常量

2、const 在 * 的后面表示 p 本身是常量,但是 p 指向的不一定是常量


const 型的指针有什么用?

char *strcpy(char *dst, const char *src);

字符串处理函数 strcpy,它的函数功能是把 src 指向的字符串拷贝到 dst 中


五、头文件的引入

1、为什么需要头文件?

函数的声明是很重要的

当我们在一个庞大的项目中,有很多个源文件,每一个源文件中都有很多个函数,并且需要在各个文件中相互穿插引用函数

怎么解决函数的声明问题?靠头文件


2、#include 包含头文件时,用 <> 和 "" 的区别

<> 用来包含系统自带的头文件,系统自带指的是不是你写的,是编译器或者库函数或者操作系统提供的头文件

"" 用来包含项目目录中的头文件,这些一般是我们自己写的


3、防止重复包含头文件

#ifndef __AiR_H__

#define __AiR_H__


// C 语言头文件中的声明


#endif


4、写程序时最好不要在头文件中定义变量

因为这时该头文件被多个源文件包含时,就会出现重复定义问题

全局变量的定义就应该放在某个源文件中,然后在别的源文件中使用前是 extern 声明



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值