常量和变量
常量和变量
苏丙榅1. 常量和变量概述
所谓常量就是在程序运行过程中,其值不能被改变的量,在C语言中,常量有很多种不同的类型,如下表:
常量类型 | 示例 |
---|---|
整型常量 | 100,200,-100,0 |
浮点型常量 | 3.14 , 0.125,-3.123 |
字符型常量 | ‘a’,‘b’,‘1’,‘\n’ |
字符串常量 | “a”,“ab”,“12356” |
变量(variable)可以理解成一块内存区域的名字。通过变量名,可以引用这块内存区域,获取里面存储的值。由于值可能发生变化,所以称为变量,否则就是常量了。
接下来一节我们来学习一下如何去定义一个变量名。
2. 变量名
变量名在 C 语言里面属于标识符(identifier)
,命名有严格的规范。
- 只能由字母(包括大写和小写)、数字和下划线(
_
)组成。 - 标识符中字母区分大小写。
- 不能以数字开头。
- 第一个字符必须为字母或下划线。
- 标识符不能是关键字。
- 长度不能超过63个字符。
下面是一些无效变量名的例子:
1 | 2bdog // 不能数字开头 |
另外,两个下划线开头的变量名,以及一个下划线 + 大写英文字母开头的变量名,都是系统保留的,比建议自己这样给变量起名。
1 | // 不建议的起名方式: |
3. 数据类型关键字
在C语言中为我们提供了一系列的基本类型关键字,通过这些关键字来指定定义出的变量的类型。
K&C给出了7个与类型相关的关键字
,C90标准添加了2个关键字,C99标准又添加了3个关键字,如下表:
K&R 是指《The C Programming Language》一书的作者Brian Kernighan和Dennis Ritchie,它是一本经典的C语言教材。
K&R 给出了7个与类型(type)相关的关键字:
类型 描述 char
表示字符类型 short
表示短整数类型 unsigned
表示无符号类型的整数 int
整数类型 long
表示长整数类型 float
表示单精度浮点数类型 double
表示双精度浮点数类型 C90 、C99标准添加的关键字
类型 描述 signed
表示有符号类型的整数 void
表示无类型,常用于函数返回类型或函数参数列表中的空参数 _Bool
与 bool
关键字具有相同的作用,用于声明布尔类型关于
_Complex
和_Imaginary
分别用于表示复数
和虚数
(二者皆是数学概念),不常用,初学者可以无视,直接跳过即可。
4. 变量的声明和定义
在C语言中变量的声明和定义是有区别的,它们的区别就是是否会分配存储空间:
- 声明是指在程序中提前告诉编译器变量的名称和类型,而
不进行实际的内存分配
。 - 定义是指除了告诉编译器变量的名称和类型之外,还
会为变量分配内存
。
4.1 变量的定义
C 语言的变量,必须先定义后使用。如果一个变量没有定义,就直接使用,会报错。每个变量都有自己的类型(type),定义变量时,必须把变量的类型告诉编译器。
在C语言中,变量的定义方式是这样的:
1 | // 语法 |
定义了一个名为age
的变量,它对应的数据类型是整形
。
如果几个变量具有相同类型,可以在同一行定义 ,如下所示:
定义变量但未初始化:
1
2
3
4
5int id, age, length;
// 上面一行代码相当于下面三行
int id;
int age;
int length;定义变量并初始化:
1
2
3
4
5
6
7int id = 9, age = 2, length = 7;
// 上面一行代码相当于下面三行
int id = 9;
int age = 2;
int length = 7;
// 语法正确, 但是不建议这样写, 容易让人误以为 id 也是有初始值的
int id, age = 2;对于上面的代码来说
等号左侧
的我们可以将其称之为变量,等号右侧的值
我们可以称之为字面量,字面量(literal)指的是代码里面直接出现的值(注意必须是一个值,一个值,一个值)。
下面举例说明:1
2
3
4int id = 9; // 9 是字面量, id 是变量
int age = 2; // 2 是字面量, age 是变量
int length = 7; // 7 是字面量, length 是变量
int size = length; // size 和 length 都是变量
注意事项:定义变量的语句必须以分号结尾。一旦变量被定义,它的类型就不能在运行时修改了。
4.2 变量的声明
从广义的角度来看,在定义变量的时候也包含着对变量的声明,所以下面例子中的语句既是声明也是定义:
1 | int count; |
但是有一种情况是实实在在的变量声明,此时需要用到一个关键字extern
,将它置于要声明的变量的前面,如下:
1 | // 通过 extern 关键字告知编译器 number,count 变量已被定义,类型是int |
上面两句代码表示整形变量number
和count
已经在其它位置被定义出来了(假设是在源文件 a.c
中定义的),这就意味着变量对应的内存空间都已分配完毕,接下来需要在源文件b.c
中使用这两个变量,此时就需要告诉编译器这两个变量已经存在了,要做的事情就是对变量进行声明,所以在使用之前把上面两句代码写到源文件b.c
中就可以了。
4.3 变量的赋值
C 语言会在变量定义时为它分配内存空间,但是不会清除内存里面原来的值。这导致定义变量以后,变量会是一个随机的值
。所以,变量一定要赋值以后才能使用。赋值操作通过赋值运算符(=
)完成。
1 | int number; |
上面的例子中定义了一个整形变量number
并且没有初始化,所以它的默认值是随机的,此时可以通过=
为其指定一个正确的值,当然我们也可以通过=
去修改某一个变量的值(变量对应的内存中的数据被覆盖了
)。
=
前后的空格不是必须的,但建议大家加上,这是一种良好的编程习惯。
1 | int number = 123; |
对于示例中的number
而言不存在值为随机数的情况,因为在定义这个变量的时候就已经进行了初始化。
对于示例中的x, y, z
而言,它们的值是随机的,如果想要给这三个变量设置相同的值,可以将赋值操作写到一行(x = y = z = 250;
)。
4.4 常量的定义
在C语言中想要定义常量(Constant),我们必须要了解常量有什么特点:
- 常量是用来存储不可变的数据,其值在程序执行过程中不能被修改。
- 常量在使用前可以直接赋值,一旦赋值后就不能再修改了。
- 常量的内存空间在编译时就确定,并且常量通常存储在只读存储器中(如常量区)。
- 常量的值在程序中可以直接使用,通常用于表示固定的数值、字符串或者其他不可变的数据。
在C语言中想要定义常量和定义变量差不多,但是需要多使用一个关键字const
,通过这个关键字标记标识符中存储的值是只读的、不可修改的。
1 | const int value1 = 520; // 整型常量 |
在C语言中,const int
和 int const
没有实质性的区别,它们都用于声明一个常量整数,表示整数是一个常量,其值不可更改。相比较而言const int
这种形式更常用一些。
在定义常量的时候有一些细节必须要知道,否则会出现语法错误:
- 定义常量的时候必须直接进行初始化。
- 定义出的常量对应的值是不允许修改的。
1 | const int num = 99; // ok |
- 第
1
行:定义了常量 num 并进行了初始化,常量值为99
- 第
2
行:定义了常量 count 没有进行初始化,常量值是随机
的 - 第
3、4
行:语法错误, 无法对常量进行赋值
4.5 printf() 函数
printf()
的作用是将参数文本输出到屏幕。它名字里面的f
代表format
(格式化),表示可以定制输出文本的格式。该函数是标准C库
函数,函数在stdio.h
中进行了声明,其函数原型如下:
1 |
|
通过函数声明可以得知:
- 函数返回值为整形,也就是函数执行完毕之后会返回一个整数
- 函数的参数是一个字符串(
char* 类型
) - 这是一个变参函数,即参数个数不定(
… 表示变参
)
如果想要打印一个字符串,对应的语句可以这样写:
1 | printf("Hello World\n"); |
上面语句中要输出的字符串为Hello World
,在C/C++中字符串要放到一对双引号中(“”
),末尾的\n
是一个换行符,这是一个特殊字符。
使用printf
函数不仅可以打印常量字符串,还可以打印变量的值,此时就需要用到一些占位符,不同的占位符对应的数据类型也不同,下面先介绍一些常用的占位符,占位符的第一个字符一律为百分号%
:
占位符 | 描述 |
---|---|
%c |
字符,对应 char 类型 |
%d |
十进制整数, 对应int 类型 |
%ld |
十进制整数,对应 long int 类型 |
%s |
字符串, 对应 char* 类型 |
%f |
浮点数(小数),对应 float 和 double 类型 |
%o |
八进制整数 |
%x |
十六进制整数 |
%% |
输出一个百分号 |
printf()
可以在输出文本中指定占位符。所谓“占位符”,就是这个位置可以用其他值代入
。接下通过举例来为大家演示占位符的使用方法:
1 |
|
- 第 1 行:
%d
表示整数,会被替换为3
- 第 2 行:
%s
表示字符串,会被替换为Tom
- 第 3 行:
%c
表示字符,按照从前到后的顺序依次被替换为A
和B
以上语句打印出的信息如下:
1 | There are 3 apples |
printf()
参数与占位符是一一对应关系,如果有n
个占位符,printf()
的参数就应该有n + 1
个。如果参数个数少于对应的占位符,printf()
可能会输出内存中的任意值。
5. 类型限定符
限定符 | 含义 |
---|---|
extern |
声明一个变量,extern声明的变量没有建立存储空间。extern int a; |
const |
定义一个常量,常量的值不能修改。const int a = 10; |
volatile |
防止编译器优化代码 volatile int a = 10; |
register |
定义寄存器变量,提高效率。register是建议型的指令,而不是命令型的指令,如果CPU有空闲寄存器,那么register就生效,如果没有空闲寄存器,那么register无效。register int counter = 9; |
在现代编译器中,对于自动变量的存储和访问,编译器通常会根据程序的优化级别和目标平台上的寄存器数量等因素进行智能优化。因此,程序员通常不需要显式使用 register
关键字来优化变量的存储和访问。