C语言杂项

全局变量和局部变量

生存周期:从定义位置开始到该变量被释放
作用域:变量的有效作用范围
定义位置:函数体内 函数体外
存储区域:
静态区 栈区 堆区 代码常量区

全局变量:
	生存周期:从定义位置开始到文件结束
	作用域:定义该变量的整个文件
	定义位置:函数体外,经常定义在主函数的上方
	存储区域:静态区	----   自动申请,自动释放

局部变量:
	生存周期:从定义位置开始到定义它的函数结束
	作用域: 定义该变量的函数体内
	定义位置:函数体内
	存储区域:栈区 --- 变量先入后出
	
当全局变量 和  局部变量重名时,以局部变量为主

typedef

作用:给数据类型取别名
u8 u16 u32
定义格式:
typedef 数据类型 别名;

预处理指令

以“#”号开头的预处理命令
预处理就是指在进行编译的第一遍扫描(词法扫描和语法分析)之前所做的工作
1.宏定义
允许用一个标识符来表示一个字符串,称为“宏”
使用格式:
#define 标识符 字符串
注意:是使用标识符原样替换字符串
两种情况:
	(1)不带参的宏定义
	eg:
		#define MAX 255
		#define PI 3.1415
	(2)带参宏定义
	#define f(x) x+2

2.文件包含
作用:包含一个头文件,之后就可以使用该文件中的函数
形式:
	#include <头文件.h> ---- 本身就有的文件
	#include "头文件.h" ---- 自定义的头文件
	这两种形式仅仅是优先搜索路径不同
	
3.条件编译
预处理程序提供了条件编译的功能,可以按不同的条件去编译不同的程序部分,因此产生
不同的目标代码文件
条件编译有三种形式,分别介绍如下。
1)第一种形式。
#ifdef 标识符
	程序段1
#else
	程序段2
#endif
它的功能是,如果标识符已被“#define”命令定义过,则对“程序段 1”进行编译;否则对“程序段 2”进
行编译。如果没有“程序段 2”(它为空),本格式中的#else 可以没有,即可以写为如下形式:
#ifdef 标识符
	程序段
#endif

#endif一定要存在

2)第二种形式。
#ifndef 标识符
	程序段1
#else
	程序段2
#endif
与第一种形式的区别是将“ifdef”改为“ifndef”。它的功能是,如果标识符未被“#define”命令定义过则对
“程序段 1”进行编译,否则对“程序段 2”进行编译。这与第一种形式的功能正相反。

条件编译 和 if-else 的不同
条件编译时未参与编译的程序段不会被差错,因为程序的查错在编译阶段
if-else 根据条件决定哪部分代码被执行,哪部分代码不被执行,但是,哪怕代码没有执行,也是
会参与编译的

在嵌入式C语言中,经常会使用第二种形式编写头文件
以学生管理系统为例:
将相关的函数全部封装在student.c当中,将student.c 中的函数在student.h文件中声明
头文件编写格式:
	#ifndef 标识符
			//该标识符只要是工程中没有出现过的标识符即可,一般写成文件名的大写形式
	#define 标识符
	
	//函数声明
	
	#endif

3)第三种形式
#if 常量表达式
	程序段1
#else
	程序段2
#endif
它的功能是,如果常量表达式的值为“真”(非 0),则对“程序段 1”进行编译,否则对“程序段 2”进行
编译。因此,可以使程序在不同条件下完成不同的功能。

static

关键字:修饰变量存储在静态区

变量定义在函数体外,为全局变量,存储在静态区
如果在定义时没有初始化,则静态区会自动初始化全局变量,默认初始值是0

变量定义在函数体内:局部变量。局部变量如果没有使用 static 修饰,就是默认
动态局部变量(使用auto修饰),自动分配,自动释放,此时是存储在栈区,栈区
的特点先入后出,不会自动初始化空间,也就是说,局部变量使用前需要考虑是否
要初始化;
局部变量也可以使用static去修饰,变成静态局部变量,存储在静态区,被static
修饰的变量只会被定义一次 和 初始化一次
注意:无论是动态局部变量 还是 静态局部变量,它们的作用域没有改变,仍然是
在定义它的函数当中,但是被声明成静态局部变量,它的生存周期改变了,会随着
文件的结束而释放

对于static关键字,在C语言中,主要应用分为:
①在函数体内,将变量声明成静态变量,那么该变量在程序运行过程中的值是可保留的
②在模块内(在函数体外) --- 全局变量,一个被声明成静态变量的变量,在模块内可以
被其他函数访问,但是不能被模块外的其他函数访问
/*
补充:extern 
声明变量为外部变量
*/
③在模块内一个被声明成静态的函数只能被该模块内的其他函数调用,不能被其他模块的函数调用,
也就是说,这个函数被限制在声明它的模块的本地范围使用

const

关键字:修饰变量的空间只读
int a = b;
//a : 变量,对a的空间进行写操作
//b :变量/常量,对b的空间进行读操作

如果使用 const 对空间进行修饰,则该空间只能读,不能写

对const修饰的空间必须要初始化,否则之后不能赋值

修饰普通变量
int a;
---> int const a;
	 const int a;
	 没有区别,都是就是变量的空间只读

修饰指针
#include <stdio.h>

int main(void)
{
	int a = 3;
	int b = 4;
	int c = 5;
	const int *p = &a;
	int const *q = &b;//①②相同,const 修饰指针指向对象的空间	常量指针
	int * const k = &c;//const 修饰指针自身的空间	指针常量
	*p = 6;//不合法
	p = &b;//合法
	*q = 7;//不合法
	q = &c;//合法
	*k = 8;//合法
	k = &a;//不合法
	return 0;
}
const 修饰指针时,如果修饰的是指针指向对象的空间,则指针指向对象的空间不能被
重新赋值;如果修饰的是指针自身的空间,则指针不能重新指向

const int * const p;
//指针指向对象的空间 --- 只读
//指针自身的空间 --- 只读
指针常量 + 常量指针	= 常量指针常量

const 修饰空间的原则:离谁近,谁只读

const作用:
	1.可以定义变量,修饰函数参数、函数返回值
	2.让编译器保护那些希望不被改变的变量
		被const修饰的对象,受到强制保护的,可以防止其他代码无意识的改变,减少bug
	3.为阅读代码的人提供有用信息,表示该变量的某种特性

共用体

共用体(union,或称为联合体) 是一个能在同一个存储空间里 (但不同时) 存储不同类型数据的数据类型。
//共用体 和 结构体 的类型非常相似
定义结构体类型的形式:
struct 结构体类型名{
成员列表;
};
定义共用体类型的格式:
union 共用体类型名{
成员列表;
};

定义共用体变量的格式:
union 共用体类型名 共用体变量名;
//union 共用体类型名 是一种数据类型

共用体:成员共同使用同一块空间的数据类型

union stu2{
	int score;
	char sex;
	char name[10];
};
共用体进行初始化:
union stu2 didi = {80};
	对共用体变量进行初始化时,所赋值的数据将会以第一个成员的格式存储到空间当中,
对共用体的任意一个成员赋值,都会影响其他的成员

结构体 和 共用体的异同:
相同点:
	①使用方法类似,都是先定义类型,再定义变量
	②定义变量的方式也是类似的,有四种方法
	③指定成员的方法也是一样的,变量名.成员名
不同点:
	①定义时,使用的关键字不同,结构体:struct,共用体:union
	②对于共用体赋值时,只需要赋值一个成员即可(第一个成员)
	 对于结构体赋值时,则需要对每一个成员赋值
	③共用体成员占用一块空间,成员的起始地址相同,结构体每一个成员
	 都有自己独立的空间

枚举型

枚举类型的定义格式:
enum 类型名 {标识符1,标识符2,……,标识符n};
eg:
enum color {blue,pink,yellow,white,black,green,red};
定义了一种名为color的数据类型,这种数据类型定义的数据,只能是
blue,pink,yellow,white,black,green,red的数值中的一种
定义枚举类型时,{}中的标识符相当于整型常量,默认从0开始计数

定义枚举变量的格式:
enum 枚举类型 变量名;

枚举变量的赋值:
变量名 = 标识符;

枚举型的优点:
	提供一些标识符去替代整型变量,提高代码的可阅读性
	
如何改变枚举型中标识符的值???
定义枚举类型时,直接对标识符赋值,该标识符以及它后面的标识符将全部改变(依次+1)
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值