一、变量
变量就是可以变化的量,而每个变量都会有一个名字(标识符)。变量占据内存中一定的存储单元。使用变量之前必须先定义变量,要区分变量名和变量值是两个不同的概念。
现实生活中我们会找一个小箱子来存放物品,一来显得不那么凌乱,二来方便以后找到。计算机也是这个道理,我们需要先在内存中找一块区域,规定用它来存放整数,并起一个好记的名字,方便以后查找。这块区域就是“小箱子”,我们可以把整数放进去了。
1.变量名(标识符)
变量名:变量名在 C 语言里面属于标识符(identifier),命名有严格的规范。
- 只能由字母(包括大写和小写)、数字和下划线(_)组成。
- 不能以数字开头。
- 变量名不能包含除 _ 以外的任何特殊字符,如:%、# 、逗号、空格等
- 长度不能超过63个字符。
- 不可以使用32个保留关键字
// 无效变量名
$zj j**p 2cat Hot-tab tax rate don't
// 有效变量名
Radiu salary AotuGun Knotted_Wool H301
变量名严格区分大小写,start、Start、START是不同的变量名。
2.声明变量
C语言
的变量,必须先声明后使用。如果一个变量没有声明,就直接使用,会报错。
每个变量都有自己的类型(type)。声明变量时,必须把变量的类型告诉编译器。
int one;
此处声明了变量one
,并且指定了他的类型为int
(整数)
如果在有多个同类型变量时,我们可以同时声明
int one, two;
// 等于
int one;
int two;
注意:
- 声明变量的语句必须以分号结尾。
- 一旦声明,变量的类型就不能在运行时修改。
3.变量赋值
C语言
会在变量声明时,就为它分配内存空间,但是不会清除内存里面原来的值。这导致声明变量以后,变量会是一个随机的值。所以,变量一定要赋值以后才能使用。
赋值操作通过赋值运算符=
完成。
// 声明了变量num
int num;
// 给变量num赋值888
num = 888;
代码语言:javascript复制变量的值应该与类型一致,不应该赋予不是同一个类型的值,比如num的类型是整数,就不应该赋值为小数。虽然 C语言会自动转换类型,但是应该避免赋值运算符两侧的类型不一致。
// 在声明变量的同时赋值给num
int num =888;
当拥有多个同类型变量时,可以在一行写多个
代码语言:javascript复制int x = 1, y = 2;
赋值表达式有返回值,等于=
右边的值。
int x, y;
x = 1;
y = (x = 2 * x);
上面代码中,变量y
的值就是赋值表达式(x = 2 * x)
的返回值2
由于赋值表达式有返回值,所以 C 语言可以写出多重赋值表达式。
int x, y, z, m, n;
x = y = z = m = n = 3;
上面的代码,一次为多个变量赋值。赋值运算符是从右到左执行,所以先为n
赋值,然后依次为m、z、y
和x
赋值。
C 语言有左值(left value)和右值(right value)的概念。左值是可以放在赋值运算符左边的值,一般是变量;右值是可以放在赋值运算符右边的值,一般是一个具体的值。这是为了强调有些值不能放在赋值运算符的左边,比如x = 1是合法的表达式,但是1 = x就会报错。
4.变量的作用域
作用域(scope)指的是变量生效的范围。C语言的变量作用域主要有两种:文件作用域(file scope)和块作用域(block scope)。 文件作用域(file scope)指的是,在源码文件顶层声明的变量,从声明的位置到文件结束都有效。
代码语言:javascript复制int a = 1;
int main(void) {
printf("%in", a);
}
上面示例中,变量a
是在文件的顶层声明的,从声明位置开始的整个当前文件都是它的作用域,可以在这个范围的任何地方读取这个变量,比如函数main()内部就可以读取这个变量。
块作用域(block scope)指的是由大括号{}
组成的代码块,它形成一个单独的作用域。凡是在块作用域里面声明的变量,只在当前代码块有效,代码块外部不可见。
int a = 12;
if (a == 12) {
int b = 99;
printf("%d %dn", a, b); // 12 99
}
printf("%dn", a); // 12
printf("%dn", b); // 运行报错
上面例子中,变量b
是在if
代码块里面声明的,所以对于大括号外面的代码,这个变量是不存在的,所以运行会报错。
代码块可以嵌套,即代码块内部还有代码块,这时就形成了多层的块作用域。它的规则是:内层代码块可以使用外层声明的变量,但外层不可以使用内层声明的变量。如果内层的变量与外层同名,那么会在当前作用域覆盖外层变量。
代码语言:javascript复制{
int i = 10;
{
int i = 20;
printf("%dn", i); // 20
}
printf("%dn", i); // 10
}
上面示例中,内层和外层都有一个变量i
,每个作用域都会优先使用当前作用域声明的i
。
最常见的块作用域就是函数,函数内部声明的变量,对于函数外部是不可见的。for
循环也是一个块作用域,循环变量只对循环体内部可见,外部是不可见的。
for (int i = 0; i < 10; i )
printf("%dn", i);
printf("%dn", i); // 报错
上面示例中,for
循环省略了大括号,但依然是一个块作用域,在外部读取循环变量i
,编译器就会报错。