这是一个C语言系列文章,如果是初学者的话,建议先行阅读之前的文章。笔者也会按照章节顺序发布。
变量
对于初学编程语言的人来说,变量这个概念第一反应或许是数学中的自变量x。在编程中,与之相似,即变量中存放的数据可以更改。但是与数学不同的是,变量在中还有额外的属性。
一个变量包含的属性:
- 变量的值
- 变量所处的位置
对于第一点,大家很好理解,x=1,那么变量x的值为1,x = x + 1之后,x的值为2。
对于第二点,我们不得不提及两个事物——内存与寄存器。
这里我们暂时先不介绍寄存器,留待后续章节讨论,这并不会妨碍你学习和使用C语言。
在一般情况下,C语言中定义的变量都存储在内存中(请暂时忽略,函数的部分参数是存在寄存器中的事实)。内存是一块连续的区域,如果类比的话我们可以参考路边划线的停车位。
一组停车位相当于一段内存空间,而每一个停车位就相当于这段内存空间中的一部分片段。我们的变量就好比是一个停车位区域。
额外补充一下,内存的最小存储单位是比特(bit),也叫位,即只能存储一个值,这个值要么是0,要么是1。8个bit称作一字节(byte)。
为了能更好的管理停车位,我们都要对停车位进行命名编号,便于我们快速定位某一个车位,内存亦然。因此,也就出现了一个概念叫做地址。
假设,图片中离镜头最近的车位为1号车位,编号逐个向远处递增。同时,我给1号车位区域起了个名字叫x。这时,有一辆奔驰停入了1号车位,那么我也可以说,x中的车是奔驰车。
等价到内存这个概念上就是,我有一个变量叫x,它在内存中的地址是1,它的值是奔驰。
随后,奔驰开走了,又来了辆路虎。那么这时,我可以说变量x的值是路虎,它的内存地址是1。
常量
前面介绍了变量,表示一段内存中的数据是可以变化的。与之相对的,就是常量,即一段内存中存放的数据是不可改变的。这就好比一张光盘(暂时不考虑可擦写的…),一旦写入内容,就不可再更改了。
常量在C语言中的关键字为const,初学者先不必纠结,且继续阅读。
数据类型
本小节讨论的是基础数据类型,因此不会讨论数组这样的结构。
在编程语言中,人为的给定了存放在内存中数据的类型,在C语言中,这些类型有:
- 整型,即整数
- 浮点型,即实数
- 字符型,即单个的可打印字符(什么叫可打印的我们后面会说到)
- 空类型,即无类型
- 指针类型
下面我们将逐个类型说明,初学者暂时不需要死记硬背每一个类型的数值范围,在有需求时查阅范围即可。
整型分为:
- 有符号短整型,对应关键字为short,占用2字节内存,即该类型的数据值范围为-32,768 到 32,767
- 无符号短整型,对应关键字为unsigned short,占用2字节内存,数据值范围0 到 65,535
- 有符号整型,关键字int,占用4字节(注意,在windows上这个类型占2字节),数据值范围-2,147,483,648 到 2,147,483,647
- 无符号整型,关键字unsigned int,占用4字节,数据值范围0 到 4,294,967,295
- 有符号长整型,关键字long,32位系统上占4字节,数据值范围-2,147,483,648 到 2,147,483,647,64位系统上占8字节,数据值范围-9223372036854775808到9223372036854775807
- 无符号长整型,关键字unsigned long,32位系统上占4字节,数据值范围0 到 4,294,967,295,64位系统上占8字节,数据值范围0到18446744073709551615
- 还有long long和unsigned long long,占8字节内存,数据值范围分别为-9223372036854775808到9223372036854775807和0到18446744073709551615
浮点型分为:
- 单精度浮点型,关键字为float,占4字节,数值范围1.2E-38 到 3.4E+38,精度是精确到6位小数
- 双精度浮点型,关键词为double,占8字节,数值范围2.3E-308 到 1.7E+308,精度是精确到15位小数
- 还有一种,码哥我词穷了,不知道中文该怎么叫了,关键词为long double,占16字节,数值范围3.4E-4932 到 1.1E+4932,精度是精确到19位小数
可以看到,实数都是有一个精度范围的,如果超出这个精度范围就会造成精度损失,因此在运行一些除法运算后再执行乘法力图恢复初始值时有时是不可能的。
字符型分为:
- 有符号字符,关键词char,占1字节,数值范围-128 到 127
- 无符号字符,关键词unsigned char,占1字节,数值范围0 到 255
其中char型字符为可输出字符,参考ASCII码表来找到其对应的输出到终端上的字符:
ASCII码表
其中,值为0~31和127的字符是控制类字符,剩余为可显示字符。
空类型:又称为void型,关键字为void,表示无类型或者不知其类型。
指针类型:本节暂时不讨论,留待后续专门讨论指针的文章中详述。
看一些例子
到此,我们来看一下各种类型的例子,巩固一下前面的内容。
整型示例:
short var_1 = -1; //有符号短整型
unsigned short var_2 = 65535; //无符号短整型
int var_3 = 1000000; //有符号整型
unsigned int var_4 = 999999999; //无符号整型
long var_5 = 9876278913; //有符号长整型
unsigned long var_6 = 12871236897; //无符号长整型
long long var_7 = -1238123871; //码哥词穷,这类型你就当是长长整型吧...
unsigned long long var_8 = 1987623453;
const int a = 10; //整型常量a的值为10
const short b = 127; //短整型常量b的值为127
浮点型示例:
float var_1 = 3.141592; //单精度浮点数
double var_2 = 1.124987651; //双精度浮点数
long double var_3 = 3231.3123817682;
const float pi = 3.141592; //单精度浮点型常量pi的值为3.141592
字符型示例:
char var_1 = 70; //有符号字符型
char var_2 = 'F'; //有符号字符型,var_2和var_1其实是相等的,在ASCII码表中,F的十进制值即为70
//如果要给char型变量赋值ASCII码表中可显示字符,需要用单引号扩住,且单引号内只能有一个字符
//但有一种特例,叫做转译字符例如下面:
char var_3 = 'n'; //这里的 就是转义字符,当编译器遇到转自字符时会吞掉转义字符,
//并查看其后字符是什么字符,然后转成相应特定字符,本例中n为换行符,即ASCII中值为10的换行符。
unsigned char var_4 = 255; //无符号字符型
const char enter = 'n'; //字符型常量enter的值为 n
变量以及常量的命名要求
上面的示例中码哥对变量和常量的名字命名都是形如:
var_xxx
其实在C语言中,变量与常量的名字命名是有规范的,要求如下:
名字必须以字母或者下划线开头,后面的字符既可以是字母也可以是下划线也可以是数字。
所以,形如如下名字是不合法的:
123_abc
-a
+a
123bcd
类型转换
先来看一个例子体会一下:
int a = 5.0 / 2;
/表示,即除法。这时a的值是多少呢?
答案是2,而不是2.5。这里就是类型转换起了作用。5.0是浮点数,浮点数除整数,得到的结果还是浮点数,但是这个值赋给了整型变量a,因此除法的结果需要满足a的类型约束,只保留整数部分,因此就是2。这里也不存在四舍五入一说,即便是2.99999也会是2,而不是3。
上面的这种转换叫做自动类型转换,与之相对的转换模式叫强制类型转换。
我们先看下强制类型转换的例子,也就能理解上面这个例子叫自动类型转换了。
int b = (int)2.5;
在这个例子中,如果不在2.5前加(int),那么编译器会给出警告,说你这么写等于是“偷摸地”将双精度浮点数转换为整型了。为了避免这个警告(当然,取整数也是符合这个例子中我的预期的,即我要的也是整数),在2.5前加入:
(基础数据类型) //本例为(int)
将2.5先转成整型2,然后赋给变量b。
下面看一些其他类型转换的例子:
unsigned char var_1 = (unsigned char)'F'; //因为'F'默认为char型
short var_2 = (short)999999; //999999为int型,直接赋值会爆出警告,强制类型转换后不会有警告,但是var_2的值为16959
这里var_2的值为16959的原因是:
整型999999占4字节,其十六进制为0x000F423F。short类型占2字节,因此会将int型的低16位(即后两字节)内容赋给变量var_2,也就是0x423F,这个十六进制数转换为十进制后的值就是16959。
对于十六进制不了解的读者,可以去网上先充一下电,因为十六进制在编程中用到的频度不比整数低。