Skip to main content

变量

变量

变量表示一些不固定的数据,也就是可以改变的数据。

基本格式为 变量类型 变量名称 ;

  • 任何变量在使用之前,必须先进行声明, 只有声明了变量才会分配存储空间, 才有空间存储数据。
  • 一旦给变量指明了类型,那么这个变量就只能存储这种类型的数据
  • 变量名属于标识符,所以必须严格遵守标识符的命名原则
标识符

一个 C 程序中可能会有多个函数和变量,为了区分这些函数和变量,就给他们起名, 这个名称就是标识符。标识符命名规则如下

  • 推荐由字母(a~zA~Z)、数字、下划线组成
  • C99 和 C11 的 UCN(通用字符名称,Universal Character Names)支持绝大多数现代语言字符作为标识符名。
  • 不能包含除下划线以外的其它特殊字符串
  • 不能以数字开头
  • 不能是 C 语言中的关键字
  • 标识符严格区分大小写, test 和 Test 是两个不同的标识符

变量的第一次赋值,我们称为初始化?

// 先定义,后初始化
int value;
// 利用 = 号往变量里面存储数据, 我们称之为给变量赋值
// 这里的 = 号,并不是数学中的“相等”,而是 C 语言中的 赋值运算符
// 赋值的时 = 号的左侧必须是变量 (998=value,错误)
value = 998;

// 定义时同时初始化
int a = 4;

// 连续定义多个变量,之间用逗号(,)号隔开
int b = 4, c = 2;

// 结合使用
int d = 3, e;
e = 5;

// 多次赋值每次赋值都会覆盖原来的值
int i = 10;
i = 20; // 修改变量的值

// 可以将一个变量存储的值赋值给另一个变量
int a = 10;
int b = a; // 相当于把a中存储的10拷贝了一份给b
tip

为了方便阅读代码, 习惯在 = 的两侧 各加上一个 空格

常量

定义单个常量有两种方式:#define 常量名 常量值const 数据类型 常量名 = 常量值;

  • 常量必须在定义时就初始化,不能先定义后赋值
  • 常量名通常使用大写字母,遵循标识符的命名规则
  • 常量在程序运行过程中,一旦定义,就不能再修改它的值。
info

#define 与 const 的区别

  • #define: 没有类型检查。在编译预处理阶段进行简单的文本替换,不占用内存空间,不能直接一行定义多个。仅能定义整型常量。
  • const: 有类型检查。在编译时进行类型检查,有明确的数据类型,占用内存空间,可以直接一行定义多个。可以定义多种数据:整数常量、浮点数常量、数组等等。

const 提供了更好的类型安全性和调试支持,是现代 C 编程的首选方式。

#define

#include <stdio.h>
// 在程序开头使用 #define 预处理器指令
#define PI 3.14159
#define HI "Hello,World"

int main(){
printf("PI = %f\n", PI);
printf("%s\n", HI);
return 0;
}

const

#include <stdio.h>

int main(){
// 在程序中使用 const 关键字
const int MAX_SIZE = 100;
// 一行定义多个 const 常量
const int MIN_SIZE = 10, DEFAULT_SIZE = 50;
// 定义多个 const 常量推荐分开写更清晰
const double AAA = 100.0,
BBB = 200.0,
CCC = 300.0;
printf("MAX_SIZE = %d\n", MAX_SIZE);
return 0;
}
一些明示常量
//  使用limit.h和float头文件中定义的明示常量
#include <stdio.h>
#include <limits.h> // 整型限制
#include <float.h> // 浮点型限制
int main(void)
{
printf("Some number limits for this system:\n");
printf("Biggest int: %d\n", INT_MAX);
printf("Smallest long long: %lld\n", LLONG_MIN);
printf("One byte = %d bits on this system.\n", CHAR_BIT);
printf("Largest double: %e\n", DBL_MAX);
printf("Smallest normal float: %e\n", FLT_MIN);
printf("float precision = %d digits\n", FLT_DIG);
printf("float epsilon = %e\n", FLT_EPSILON);

return 0;
}
/*
Some number limits for this system:
Biggest int: 2147483647
Smallest long long: -9223372036854775808
One byte = 8 bits on this system.
Largest double: 1.797693e+308
Smallest normal float: 1.175494e-38
float precision = 6 digits
float epsilon = 1.192093e-07
*/

enum

在实际生活中,有些变量的取值被限定在一个确定的范围内。例如:考试评分等级为A、B、C。星期的范围是1-7。

“枚举”类型的定义中列举出所有可能的取值, 被说明为该“枚举”类型的变量取值不能超过定义的范围。

  • C 语言编译器会将枚举元素作为整型常量处理,称为枚举常量。
  • 枚举元素的值取决于定义时各枚举元素排列的先后顺序。未定义的情况下,元素值为前一个元素加 1,如果首个元素未定义则值为 0。
  • 也可以在定义枚举类型时改变枚举元素的值
  • 枚举内已经用过的标识符名称不能再用。

枚举的类型的主要作用是提高代码的可读性。枚举在本质上更接近#define定义的整型常量,不支持浮点数和数组,多用作常量集合。了解基本使用即可。

枚举类型是基本数据类型(非构造类型),表示有限集合的特殊类型

枚举类型的定义格式:

enum 枚举名 {
枚举元素1,
枚举元素2,
……
};

枚举的定义

#include <stdio.h>
enum Demo {
Spring, // 第一个枚举元素的值未定义,所以为 0
// Spring = 100, // 已经用过的标识符不能再用,会报错。
Summer = 10, // 第二个枚举元素定义值,所以为 10
Autumn, // 第三个枚举元素未定义,所以为前一个元素加 1,即 11
Winter = 'A', // 第四个枚举元素定义值为char,所以为 'A'对应的ASCII码值 65
A, // 第五个枚举元素未定义,所以为前一个元素加 1,即 66
//B = 1.0, // ❌第六个枚举元素定义值为浮点数,会报错
};

int main(int argc, const char * argv[]) {
// 定义枚举变量 s
// 把 enum Demo 看作一个类型整体,类比 int,那这里写法和 int s; 是一样的
// 可以在初始化时赋值
// 也可以仅标识,在后续赋值 enum Demo s;
enum Demo s = Spring;
printf("s = %d\n", s); // 0
// 可以赋值为其他枚举元素
s = Summer;
printf("s = %d\n", s); // 10
s = Autumn;
printf("s = %d\n", s); // 11
s = Winter;
printf("s = %d\n", s); // 65
s = A;
printf("s = %d\n", s); // 66
// 枚举主要是通过标识符赋值让你原本的数组更便于理解,不阻止你直接赋值为数值
// 也可以赋值为枚举元素以外的值
s = 100;
printf("s = %d\n", s); // 100
return 0;
}
tip

枚举的最佳实践

枚举的最佳实践是使用typedef关键字定义枚举类型,这样可以提高代码的可读性。

typedef enum {
STATE_A,
STATE_B
} StateType;

// 此时state的类型为StateType,就和你使用int、double、char等类型一样
StateType state = STATE_A;
warning

下面是一些不推荐的写法,因为它们可能会导致代码的可读性变差。

enum Season {
Spring,
Summer,
Autumn,
Winter
} s;//直接在定义枚举类型时,定义枚举变量。

//等价于 enum Season s;

s = Spring; // 等价于 s = 0;
// 也可以赋值为枚举元素以外的值
s = 3; // 等价于 s = winter;
printf("%d", s);


// 枚举变量可以省略类型,直接赋值
// 没有给枚举类型命名,只能在定义时创建变量(不推荐)
enum {
A,
B,
} Num;

作用域

C 语言中所有变量都有自己的作用域,变量定义的位置不同,其作用域也不同

  • 代码块:由一对花括号 {} 包围的代码区域,内部定义的变量只能在代码块内部使用。
  • {} 后面可加可不加分号,可不加是因为 {} 作为一个整体,已经明确的代表一个复合语句或代码块。加上可读性更强。

局部变量

  • 局部变量也称为内部变量
  • 局部变量是在代码块内定义的, 其作用域仅限于代码块内, 离开该代码块后无法使用
// 同一作用域范围内不能有相同名称的变量
int call(){
int i = 998;
int i = 666; // 报错, 重复定义
return 0;
}

int main(){
int a ;
{// 代码块内独立作用域,可以使用相同变量名
int a = 998;
int b = 666;
}
b = 100; // 报错, b是另一个作用域的变量,不能访问
return 0;
}

全局变量

  • 全局变量也称为外部变量,它是在代码块外部定义的变量
int i = 666;
int i = 998; // 同一作用域范围内不能有相同名称的变量
int main(){
printf("i = %d\n", i); // 可以使用
return 0;
}// 作用域结束
int call(){
printf("i = %d\n", i); // 可以使用
return 0;
}

全局变量 和 局部变量 同名时,局部变量会遮蔽(shadow)全局变量。

#include <stdio.h>
int i = 666;
int main(){
int i = 998; // 不会报错
//当全局变量和局部变量同名时,局部变量会遮蔽(shadow)全局变量。
printf("i = %d\n", i); // 998
return 0;
}