本期视频点击这里
一、数据类型
对数据进行处理是程序的基本功能之一,因此对于任何编程语言,数据类型都是重要组成部分之一。C语言中定义了较为完善的数据类型体系用于处理不同类型的数据。
(1)标识符
C语言中的标识符可以用作变量名、符号名、函数名、文件名等等功能。标识符可以包含字母、数字和下划线(不能以数字开头)。C语言是对大小写敏感的语言,因此组成相同但大小写不同的两个标识符将被当作两个不同的标识符处理。
C语言中的标识符可分为三类:
- 关键字:C语言定义了32个标识符作为关键字,这些关键字都被指定了固定的意义。用户不允许将关键字另作他用,否则程序将出错。这32个关键字包括:auto double int struct break else long switch case
enum register typedef char extern return union const float short unsigned continue for signed void default goto sizeof
volatile do if while static - 预定义标识符:如C语言标准库所定义的函数名,以及预编译处理命令等标识符也有特殊的定义。虽然挪用预定义标识符不会造成编译错误,但是会使这些标识符失去原有的意义,同时也是非常差的编程风格,因此推荐将预定义标识符与关键字同样对待。
- 用户标识符:用户根据需要定义的标识符,可以命名为变/常量、函数名等。应注意的是,标识符的命名对程序的可读性意义重大,因此需格外注意定义用户标识符时,命名应体现其含义,使阅读者可以较轻松地明白该标识符的作用。
(2)常量
常量所表示的数据在程序的运行过程中不能改变。C代码中的常量通过字面表示可以轻易区分,如各种数字如1、-2.5、3.14159.....用字面表示的数字代表数值型常量,‘A’和“abc” 等表示的是字符和字符串常量。除此之外,还可以将常量定义为符号,使用预编译指令#define:
#define PI 3.1415
另外,定义枚举类型也可以将常量用标识符表示。枚举数据类型适合个数确定而且每个元素的取值也确定的一组数据元素的定义。如将一周七天定义为枚举类型,则可用以下定义表示:
enum week { sun, mon, tue, wed, thu, fri, sat } a, b, c;
此处,从sun开始到sat七个元素分别表示0~6七个值。
枚举类型的第一个元素默认指定为0,不过我们也可以自己制定前面n个的值,后面的值则从最后一个指定值开始一次+1。如:
enum Month{Jan = 1, Feb, Mar, Apr, May, Jun, Jly, Oct, Sep, Nov, Dec} a, b, c;
(3)变量
变量指在程序运行过程中可以改变的量,是程序最重要的组成部分之一。每一个变量实际上表示的是内存中的存储单元,对某个变量进行操作实际上是对该存储单元或其中的数据进行操作。在C语言中,所有的变量必须先定义后使用,否则编译将出现错误。同常量类似,变量也具有多种不同的类型,定义某一个变量时通常指定了变量的类型,系统在编译时按照指定的类型分配相应的存储单元。
(4)整型数据
C语言中的整型数据用于表示整数类的数据类型,包括正负整数和0。整型数据可以用十进制、八进制或十六进制表示。其中表示八进制的方法为对应的八进制数字前加前缀0,表示16进制的方法为对应的16进制数字前加前缀0x。
整形数据根据占据位长的不同,可以分为short/int/long几种,具体每种类型的长度因机器不同而不同,标准中规定short的占位不多于int,而long的占位不少于int。对于目前常用的典型开发环境而言,三种类型分别占2、4、4个字节的内存单元。每一种类型都可以定义为有符号型或无符号型,默认为有符号型。整型变量在定义的时候可以同时对其赋予初值,进行初始化。例如:
unsigned int nYear = 2015; int nMonth = 012; long nMask = 0x00ff;
(5)实数型数据
实数型数据用于表示数学中的小数。实数型数据由有效数字和小数点表示,如0.12、1.2、12.0都是合法的实数型数据;或者以指数形式表示,如1.2e3表示1.2×10^3。
C语言中表示实数型数据的基本类型有float和double两种,分别表示单精度和双精度浮点数,分别占据4、8个字节的长度。在较新的C标准中还定义了long double类型用于以更高的精度处理实数型数据。标准规定long double的长度不低于double,具体需要依照环境而论。
float fPrice = 15.0; double dDistance = 3.84e5;
(5) 字符型数据
顾名思义,字符型数据用于表示ASCII码表中的一个字符。字符型数据亦有字符常量和字符变量之分,字符常量通常以单引号‘’引用,如'A'、'b'、'0'等。各种字符常量区分大小写,如'A'和'a'分别有不同的值,因为其ASCII码不同。ASCII码表中的每一个元素都可以作为一个合法的字符型数据。
字符型的数据类型为char,占据一个字节,可以表示的范围为[-128, 127]。另外无符号字符型数据类型为unsigned char,表示范围为[0, 255]。实际上,字符型数据同整数型数据的本质是一致的,所有适用于整型数据的运算都适用于字符型。
字符常量还可以通过转义字符表示。转义字符以反斜线‘\’后接一个特定字符表示一个ASCII字符。如最常用的换行符表示为'\n',制表符表示为'\t'。制表符的反斜线后还可以跟八进制或十六进制数字来表示相应的数字表示的字符,如'\101'和'\x41'表示10进制的65,也就是字符'A'。
除单个字符表示的字符型数据外,C语言还定义了字符串数据表示多个字符组成的字符串。字符串以一组双引号""引用,包含多个字符以及一个'\0'作为字符串结束标志。'\0'也是一个字符常量,其ASCII码为0,通常固定作为字符串结束的标记,在计算字符串长度时也要计入。比如字符串"Hello World!\n",包括中间的空格、最后的标点符号'!'、换行符'\n'和结束标志'\0'都是字符串的一部分,其长度为14。
二、算数运算符和算数表达式
对变量而言,对其进行计算是最重要的功能。C语言中定义了多种运算符来实现复杂的数值运算、按位运算和指针运算等。其中最基本的运算符有+-*/%五种,分别实现加减乘除和求余数操作。其中加减乘除操作可用于实数,求余操作仅适用于整型数据。这几种基本运算符需要两个值进行计算,称为“双目运算符”。此外,+-还可以作为“单目运算符”表示数值的符号。
在C语言中,可以将常量、变量、函数返回值可以通过运算符连接起来表示一个算数表达式,且该表达式以一个新的值反映式中各个运算数据的关系。
三、赋值运算符和赋值表达式
在C语言中,等号=为赋值运算符,其作用是将某一个新值赋予一个变量或存储单元。赋值运算符的左边必须是一个有写入权限的存储位置,右边必须是一个合法的有返回值的表达式。需要特别注意的是,必须注意区分赋值运算符“=”和比较运算符“==”,二者稍不留意就会误用。赋值运算符的优先级是最低的之一,仅仅高于逗号表达式。这也与C语言的使用习惯相符合,即先进行算术表达式的各种计算,最后才将结果赋予某个变量。
除了简单赋值之外,C语言中还定义了多种复合赋值运算符。复合赋值运算符是由算数运算符和赋值运算符结合组成的,可以对变量先进行运算并将运算结果赋予目标变量,可以用一条语句更新变量的值,使得程序更为简洁。常用的复合赋值运算符有+=、-=、*=、/=和%=以及其他种类。使用方法例如:
a += 10;//等价于a = a + 10; b *= c;//等价于b = b * c;
另外,对于某个变量自身加一或减一这样简单但使用频繁的操作,无论是a = a + 1还是a += 1都略显繁琐。因此C语言中定义了自增和自减运算符,分别以++和--表示。变量a自增和自减分别以a++和a--表示。需要注意到是,自增和自减运算符位于变量的前和后的含义略有区别:例如,a++和++a两者执行后都使得a自增1,但是表达式所返回的值不同。当运算符在前时,a先自增1,然后将计算后的a的值返回;当运算符在后时,表达式返回变量的原始值,然后变量a自增1。
四、比较和其他运算符
两个数值进行比较,共可能存在六种可能的关系:等于、不等于、大于、小于、大于等于、小于等于。每一种在C语言中对应的运算符分别为:==, !=, >, <, >=, <=。
此外,C语言中还定义了多种其他的运算符:
- 优先级最高的运算符是括号运算符( ),主要用于规定运算顺序和函数的参数表。其他高优先级的运算符还有数组元素下表[]、结构体成员'.'和'->'。
- 逻辑运算符:用于逻辑量的逻辑关系——与、或和非分别以&&、||和!实现。
- 位运算符:可以对变量进行按位运算是C语言在高级语言中的特色之一。实现位运算的运算符有:~(按位取反)、&(按位与)、|(按位或)、^(按位异或)。
- 条件运算符:C语言中唯一一个三目运算符,由两个符号组成:: ?。条件运算符的使用方法为:条件?表达式1:表达式2。当条件成立时,执行并返回表达式1;当条件不成立时,执行并返回表达式2。
- 取数据和取地址运算符:*和&。当目标操作数px为指针变量,*px表示指针所指向的地址的数据;相反,当目标操作数x为数据类型时,&x返回保存变量x的内存地址。
- 求数据长度:sizeof。求目标类型所占的字节数。
- 逗号运算符:" , "优先级最低的运算符,将逗号分隔的各个表达式按顺序求值。
不同运算符优先级及其优先级如下表:
优先级 | 运算符 | 描述 | 结合性 |
15 |
() [] -> . :: ++ -- |
调节优先级的括号操作符 数组下标访问操作符 通过指向对象的指针访问成员的操作符 通过对象本身访问成员的操作符 作用域操作符 后置自增操作符 后置自减操作符 |
从左到右 |
14 |
! ~ ++ -- - + * & (type) sizeof |
逻辑取反操作符 按位取反(按位取补) 前置自增操作符 前置自减操作符 一元取负操作符 一元取正操作符 解引用操作符 取地址操作符 类型转换操作符 返回对象占用的字节数 |
从右到左 |
13 |
->* .* |
在指针上通过指向成员的指针访问成员的操作符 在对象上通过指向成员的指针访问成员的操作符 |
从左到右 |
12 |
* / % |
乘法操作符 除法操作符 取余数操作符 |
从左到右 |
11 |
+ - |
加法操作符 减法操作符 |
从左到右 |
10 |
<< >> |
按位左移操作符 按位右移操作符 |
从左到右 |
9 |
< <= > >= |
小于比较操作符 小于或等于比较操作符 大于比较操作符 大于或等于比较操作符 |
从左到右 |
8 | & | 按位与 | 从左到右 |
7 | ^ | 按位异或 | 从左到右 |
6 | | | 按位或 | 从左到右 |
5 | && | 逻辑与 | 从左到右 |
4 | || | 逻辑或 | 从左到右 |
3 | ?: | 条件运算符 | 从右到左 |
2 |
= += -= *= /= %= &= ^= |= <<= >>= |
赋值操作符 复合赋值操作符(加法) 复合赋值操作符(减法) 复合赋值操作符(乘法) 复合赋值操作符(除法) 复合赋值操作符(取余) 复合赋值操作符(按位与) 复合赋值操作符(按位异或) 复合赋值操作符(按位或) 复合赋值操作符(按位左移) 复合赋值操作符(按位右移) |
从右到左 |
1 | , | 逗号运算符 | 从左到右 |