跟着肯哥(不是我)学C语言的变量和常量、跨文件访问、栈空间
栈空间还不清楚,期待明天的课程内容
C变量
变量(Variable)是用于存储和表示数据值的名称。
主要包括四个环节:定义、初始化、声明、使用
在我刚学C语言的时候,看的网课就专门强调了定义、声明和初始化。
在看这次学习营内容的时候,我对这些内容也已经很模糊了。
变量的定义是指在使用前对变量进行声明和初始化的过程。
也就是说,存在包含关系:
关于声明和初始化,我还记得当初学的时候,老师专门强调了这俩不是一回事。
变量定义
定义包括三部分:变量类型、变量名和初始值(可选)
- 如果没有初始值,那就是声明
- 如果有初始值,那就是初始化
变量类型(Variable Type)指定了变量所存储数据的类型和大小。
也就是我们熟知的int
、double
那些东西。
根据昨天的学习内容,布尔类型的关键字不是bool
,而是_Bool
。(我在此之前都以为是bool
)。
变量名(Variable Name)是给变量起名称,用于在程序引用该变量:由字母、数字、下划线组成,首字符不能是数字,不能与C语言内置关键字重名。
sizeof
是一个关键字,不是运算符,也就是说它不是函数,它是在编译时就计算出结果的而不用等待运行时。
C语言内置关键字是不包含malloc
的。因为学数据结构的时候经常用到,我之前以为它是的。
初始值(Initial Value)是可选的,用于给变量赋予一个初始值。如果在定义时没有提供初始值,变量将有一个未知的、未初始化的值。此时,变量的值是不确定的,需要在使用前对其进行赋值。
为了避免未初始化带来的问题,建议是:
- 初始化:单文件内使用时
- 声明:在跨文件定义、使用变量时
变量作用域
块作用域、函数作用域、文件作用域、全局作用域。
内层的作用域会隐藏外层的作用域。
下面这个例子除了文件作用域都用上了:
变量还有个“先声明,后使用”的问题。平时写代码的时候,只要在使用之前定义,就不会出问题。
在学着给51单片机写代码的时候,就出现问题了:变量的定义要放在整个代码块的最前面,否则无法通过编译。
int main() {
int a=0;
a=1;
int b=0;
b=1;
return 0;
}
上面的代码在C98老版本之前时无法通过编译的。
正确做法应该是把可能用到的定义,一起放到前面:
int main() {
int a=0;
int b=0;
a=1;
b=1;
return 0;
}
在老版本,即使是for循环括号里的第一个参数,也不能定义变量。现在的版本是允许的。
根据我做题的经验,这也是件好事,提醒自己一个良好的代码规范。在做算法题的时候,如果在for内定义变量,可能会出现频繁的申请释放,导致运行时间较长。
C常量
常量的值在程序执行过程中不能改变,是不可变的;这也是与变量的最大区别。
常量使用
常量使用方法有两种:直接使用、定义后使用
无需定义,直接使用:
int a = 1;
int b = 2;
int c;
c = a + b + 10; // 这个10其实就是一个常量
10
是常量这件事情,初学的时候当耳旁风了。现在回头专门说明这么一件事,才回想起来。
常量定义
与变量定义类似,不同的是常量定义需要用const
关键字修饰。
这种方式将常量定义为具有特定类型和常量性质的变量,并使用const
关键字标识。
const float PI = 3.14159;
这种方法定义的常量具有类型,可以直接参与表达式的计算和类型检查。
之前不理解为什么要有常量,使用很不方便。而且已经有define了,为什么还要有const。或许支持类型检查就是原因之一。
还有一种很少在课本上出现的定义方式:枚举enum
。
可以看出,枚举实际上也是一个int
类型。
无论是const
还是enum
,都要遵循“先声明后使用”的原则。
常量的作用
避免魔法数
通过使用常量来表示特定的数值或字符,可以避免在代码中直接使用未经解释的“魔法数”。
我也是第一次听说这个词,意思是难以理解的数字。
优化内存和存储
定义为常量的代码可能会直接纳入以Flash为存储媒介的ROM中,从而节省了宝贵的RAM空间。(肯哥原话)
期待即将学到的RAM/ROM的内容。
define
包括我看的网课跟实体书,讲常量的时候都会把#define
作为一种常量定义方式。
#define
的本质是文本替换,是一个宏定义的行为,并不是定义变量的行为
多文件编写
之前了解的多文件只是:头文件放结构体定义和函数声明,一个源文件放具体的函数定义,在用到这些函数的其他源文件中直接包含头文件即可。
但不清楚怎么共享变量。虽然了解过extern,但感觉这样耦合度太高,很容易出问题。
下面是肯哥讲的利用头文件共享变量的方式:
下面是肯哥原话
全局变量、常量:全局变量是在一个文件中定义,但在其他文件中声明的变量。通过在其他文件中使用extern
关键字声明该变量,就可以在其他文件中访问该全局变量。需要注意的是,全局变量对于整个程序是可见的,因此需要小心处理全局变量的使用,以防止命名冲突或意外修改。
头文件:可以头文件来共享变量的定义和声明。在一个头文件中定义变量,然在多个文件中包含该头文件,以实现对变量的访问。,应在一个文件中进行变量的实际定义,而在其他文件中只进行声明。
例如,在共享变量的头文件中声明一个变量:
// shared.h
extern int x // 只声明变量x
// 可以在其他文件中包含该头文件,以便访问变量x
然后,在一个源文件中定义该变量:
// file1.c
#include "shared.h"
int x = 10;
在其他源文件中包含头文件,即可访问(使用)该变量:
// file2.c
#include "shared.h"
// 可以在该文件中访问变量x