拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

9.28 标识符的作用域与可见性,指定关键字(auto,static,register,extern),预处理 编译 汇编 链接,宏定义,带参宏

9.28 标识符的作用域与可见性,指定关键字(auto,static,register,extern),预处理 编译 汇编 链接,宏定义,带参宏

标识符的作用域 与 可见性问题:

说明:

1.变量名

2.函数名

3.数组名

作用域:

发挥作用区域

{

} //C语言中 一个 {} 就是一个作用域

作用域:

局部作用域

只要是在{} 范围内的 都是局部作用域

局部作用域定义的变量 --- 局部变量

全局作用域

不在任何一个 {} 范围内的,是全局作用域

全局作用域定义的变量 --- 全局变量

可见性:

站在程序角度看,程序运行到某一刻时,哪些标识符可见(可用)

标识符的可见性的规则:

1.先定义,后使用

2.同一作用域中,不能有同名标识符

3.在不同的作用域,同名标识符,相互之间没有影响

4.如果是不同的作用域,但是作用域之间存在嵌套关系, 则,内层的作用域的同名标识符,会屏蔽外层的作用域的同名标识符。 (就近原则)

C语言5个区:

栈

堆

全局区(静态区)

字符串常量区

代码区

存储类别关键字:

main()

{

int a = 10; //局部变量 --- 定义变量 意味着开空间 --- 空间开在哪里?

}

指定关键字 来表示 数据可以放到哪来

auto int a = 10; //auto 就表示这个变量空间开在栈上

static int a = 10; //static 静态的 表示将变量 空间 开在 静态区

//静态区变量的特点:

// 1.只会被初始化一次

// 2.不能用变量初始化

// 全局变量也不能用变量初始化 --- 全局变量和静态变量,都是放在全局区(静态区)

// 3.静态局部变量的值,具有继承性

从变量角度看,

空间上:

局部变量

全局变量

时间上:

生命周期

局部变量 的生命周期 ---从定义处开始,到所在作用域结束

//程序执行到定义时,变量创建,程序执行到 作用域结束 变量销毁

全局变量

静态变量 的生命周期 ---程序运行开始后,就存在,直到整个程序结束,才销毁

./a.out

(整个程序的生命周期)

register int a = 10; //register --- 寄存器

//告诉编译器 ,将变量a 存放到 寄存器中

//关键字 ---- 建议性关键字

//考点

// 如果是register修饰的变量

// 不能做 &(取地址)运算

// 原因 --- 内存空间可以取地址,寄存器取不了

拓展:

计算机的存储体系:

寄存器

cache

内存

硬盘

从上到下,容量越来越大,价格越来越便宜,速度原来越慢

CPU + 内存 + 硬盘

unsigned int i = 0;

for (i = 0; i < INT_MAX; ++i)

{

}

//声明

extern int a; //extern --- 外部的意思 --- extern相当于是扩展了变量的作用域,

//相当于将a的作用域扩展到本文件

//修饰表示,变量存储在别的文件中,要使用式到别的文件中寻找

extern 和 static:

static

也可以修饰全局变量,表示 将该变量的作用域,限定为本文件

别的文件中无法引用(extern int a;) //static修饰全局变量 --- 限定了作用域

也可以修饰函数

//多文件编程

作用和修饰全局变量作用相同

用途:分模块

好多个函数

全局变量 int cnt;

函数

static

保护数据作用

关键字:

auto

static //背诵的第一个面试问题

// 你知道static吗?

// 解释

register

extern

预处理命令:

#include <stdio.h> //预处理命令

C提供的预处理功能主要有以下3种:

1. 宏定义

2. 文件包含

3. 条件编译

注意:

1.所有的预处理命令 都 以 # (井号)开头

编译:

gcc hello.c //编译

实际的编译过程:

预处理:

将程序中的预处理命令,执行完,将代码处理成 纯的C语言代码

编译:

将预处理完的文件,进行语法,词法分析,检查问题

生成 一份 汇编代码

汇编:

将 前面的汇编代码,最终翻译成机器代码

链接:

将用到的第三方代码 链接(拼接)成为 最终可执行程序

预处理:

gcc -E hello.c -o hello.i

编译:

gcc -S hello.i -o hello.s

汇编:

gcc -c hello.s -o hello.o

链接:

gcc hello.o -o hello

1. 宏定义

#define 标识符 字符串

#define 宏名 宏值

作用:

用宏名代替 一串文本信息

注意:

1. 宏名 --本质还是一个标识符

2. 宏名 建议 大写

3. 宏名 --符号常量

用了一个 符号(宏名) 代替 常量值

4. 宏工作的本质

文本原样替换

但是:

代码中出现在 "" (双引号)中的 宏名 ,不会被替换

5. 用途

可以用宏名 来代替一些常量

符号常量

好处,可以做到一改全改

可以提高代码可读性

#define ARRAY_SIZE 10

int array[ARRAY_SIZE]

练习:

计算一下 圆的周长和面积

带参宏:

#define 宏名(参数表) 宏值

说明:

1.带参宏 ,可以 给一些参数

形式 特别像函数调用

宏函数

2.带参宏 和 函数有本质的区别

a.函数的参数 是带类型的

b.带参宏 参数,没有类型 --就是文本

c.函数什么时候可以用?

程序运行之后

d.带参宏

在预处理阶段

就处理完了

3.带参宏 工作过程

本质上还是文本原样替换

参数是一一对应的

4.带参宏副作用

建议, 能加括号都加括号可能会改变的值,我们建议都加括号

5.所有宏定义

以换行作为结束符

6.宏的作用域

从定义出开始

往下

都发挥作用

取消宏的作用域

#undef 宏名

eg:

两个数相乘

int mul(int a,int b)

{

return a * b;

}

#define MUL(a,b) a*b

MUL(1+2,3+4) 1+2*3+4

#define MUL(a,b) ((a)*(b))

练习:

实现一个宏,找出两个数的最大值

[预处理]:

1.预处理 不是 c语言的一部分

2.预处理 命令 都是以 # 开头

3.宏定义

工作的过程 (本质)

文本替换

4.文件包含

5.条件编译

预处理---本质上都是做做文本替换

文件包含:

#include <文件名> //默认到系统的标准路径下寻找要包含的头文件

#include "文件名" //双引号 默认先到当前位置下 寻找要包含的头文件,如果找到,则包含进来

// 如果没找到,才到系统的标准路径下寻找

#include <stdio.h>

说明:

1. include 这个预处理命令执行之后,

用文件中的内容 ,替换这个 命令所在位置

2. 将来使用

<> //如果是系统的相关头文件 --- 用 <>

"" //如果是自己写的 一般用 ""

条件编译:

#if 0

......

#endif

(1)

#ifdef 标识符

程序段1

#else

程序段2

#endif

语义:

判断 标识符 是否定义了?

如果定义了 ---真

选择 程序段1

如果没定义 ---假

选择 程序段2

#ifdef 标识符

程序段1

#endif

满足条件的时候 ,添加 程序段1

不满足条件时候,啥都没有

(2).

#ifndef 标识符

程序段1

#else

程序段2

#endif

语义:

没有定义 标识符 则选择程序段1

有定义 标识符 则选择程序段

(3).

#if 表达式

程序段1

#else

程序段2

#endif

#if 表达式

程序段

#endif

#if 0

......

#endif

用途:

可以用来实现 多文件编程

printf //系统里面的函数

#include <stdio.h>

printf();

实现好的功能 .c 独立的c程序提供 或者 打包成库文件

.c //写好了功能的点c文件

.c 对应 有一个 .h (头文件)

.c --- 就是实现功能的具体代码 ---函数

.h --- 头文件 --放的是 自身需要用到 宏 类型说明 函数声明 //变量的定义 不能放头文件

//全局的

int a = 10; //a一定得开空间

extern int a; //

说明:

头文件包含

注意 --- 一定要写

#ifndef 头文件名 //要大写 前后 下划线

#define 头文件名

#endif

命令:

vsp //竖着分屏

sp

窗口之间切换:

ctrl + 两下w

编译:

所有 .c 一起编译

gcc main.c isLeapYear.c getAllDays.c .....//这些需要一起编译

返回列表