第3章基本数据类型、运算符和表达式






















◇ 学习导读

通过前面内容的学习,已经了解了C语言源程序的基本结构以及源程序包含的基本语句和合法的标识符,那么如何编写一个程序解决实际问题呢?首先,需要确定处理的对象,然后,实现功能。在计算机中,确定处理对象就是描述或定义问题所涉及对象的数据类型,实现功能就是在处理对象之间进行运算,进而通过语法规则编写语句来解决实际问题。

本章详细介绍C语言中常用的基本数据类型以及在数据处理过程中使用的基本运算符和表达式。通过本章的学习,读者将能够用基本数据类型定义问题中使用到的数据,以及用合适的运算符和表达式描述数据的简单处理过程。本章是学习C语言的重要基础。

◇ 内容导学

(1) 变量和常量的概念。

(2) 各种类型的数据在内存中的存放形式。

(3) 各种类型常量的使用方法。

(4) 各种整型、字符型、浮点型变量的定义和引用方法。

(5) 自动数据类型转换的规则以及强制数据类型转换的方法。

(6) 算术运算符、赋值运算符、逗号运算符以及sizeof运算符的使用方法。

(7) 运算符的优先级和结合性。

◇ 育人目标

《论语》的“学而不思则罔,思而不学则殆”意为: 学习而不思考就会迷惘无所得; 思考而不学习就不切于事而疑惑不解——常学习,常思考,定会有收获。

本章的基本数据类型、基本运算符及其构成的表达式都是今后学习的重要基础语法知识,也是所有高级语言学习的基础。作为初学者从基础知识开始,认真学习并了解不同数据类型的区别和用法,基本运算符、表达式的运算规则,养成良好的编程习惯和语法规则意识,可以帮助编程者避免很多基础性的语法错误。




视频讲解


 3.1C语言的数据类型

本节主要讨论以下问题。



图31C语言的数据类型分类


(1) C语言支持的数据类型有哪些?

(2) C语言的基本数据类型有哪些?

(3) C语言的构造数据类型有哪些?

学习C语言的最终目的就是编写解决实际问题的程序,而程序的操作对象是数据。计算机在处理数据时,要求数据必须具有确定的数据类型。数据类型决定了数据在内存中占有存储空间的大小、取值范围以及能够参与的运算。C语言提供了丰富的数据类型,分为基本数据类型、构造数据类型、指针类型和空类型四大类,如图31所示。

1. 基本数据类型


基本数据类型的主要特点是其值不可以再分解为其他类型。C语言中,基本数据类型有3种,它们分别是整型、实型和字符型。本章将详细介绍这3种基本数据类型。

2. 构造数据类型

为了更好地处理并表达更复杂的数据,C语言提供了构造数据类型。构造数据类型根据已定义的一个或多个数据类型用构造的方法来定义。它的最主要的特点是其值可以分解成一个或更多个成员或元素,而每个成员又是一个独立的基本数据类型或构造数据类型。C语言中,构造数据类型有4种,它们分别是数组类型、结构体类型、共用体类型和枚举类型。

3. 指针类型

指针类型是一种特殊的数据类型,同时又是具有重要作用的数据类型。其值用来表示数据在内存中的地址。指针是C语言的精髓,没有学好指针就等于没有学好C语言。

4. 空类型

函数在定义时需要给出函数的返回值的类型。若一个函数没有返回值,则其返回值的类型为空,用void表示。


 3.2数据的表现形式

本节主要讨论以下问题。

(1) 数据在程序中如何表现?表现的类型有哪几种?

(2) 常量和变量有什么区别?

(3) 常量有哪些类型?不同数据类型常量的区别是什么?

(4) 变量有哪些类型?不同数据类型变量的区别是什么?

程序中处理的数据,除了要求明确规定是哪种数据类型之外,还要求数据以一定的形式出现。在C语言中,数据的表现形式有常量和变量两种。

3.2.1常量

程序运行时其值不能改变的数据称为常量,即数据的表现形式为常量。

常量直接在程序中使用,根据其使用的形式分为两种,即直接常量和符号常量。直接常量又称值常量,是指直接将值写出来的常量。值常量有整型常量、实型常量、字符型常量和字符串常量4种。而符号常量是指用标识符表示常量,在使用符号常量前,必须用宏定义对符号常量进行定义。

【例31】输入圆的半径,输出其周长和面积。

算法分析:  

已知圆的半径r,求其周长c和面积s的公式分别为c=2πr,s=πr2。对于计算机而言,r是变化的,不确定的值称为变量,同理,依赖于r的周长c和s也是变量。

源程序: 



1/*3-1.c*/

2#include"stdio.h"

3#define PI 3.1415926/*用宏定义说明符号常量PI*/

4int main(void)

5{

6double r,s,c;/*定义3个双精度变量r、s、c*/

7scanf("%lf",&r) ;/*输入变量r的值*/

8c=2*PI*r;/*计算c的值*/

9s=PI*r*r;/*计算s的值*/

10printf("c=%lf,s=%lf\n",c,s);/*输出c、s的值*/

11return 0;

12}






程序解析: 

该程序中使用的数据有圆的半径r、圆的周长c、圆的面积s、圆周率π以及圆的周长公式中的数2。在这些数据中,前3个数据是会变化的,后两个数据是不变的,因此把前面3个数据定义成变量,分别用标识符r、c和s表示,而后面两个数据则是常量。其中,圆的周长公式中的数2直接写出,称为直接常量或值常量,圆周率π即3.14,该实型常量可以直接写出,也可以在程序中使用PI(π的谐音),这种形式出现的常量称为符号常量。使用符号常量之前,必须在程序开头写一条“#define PI 3.1415926”宏定义预处理命令。这样,符号常量PI在程序编译时会进行宏替换,值为3.1415926。

程序运行结果如下。

3↙

c=18.849556,s=28.274333

3.2.2变量

程序运行时其值可以被改变的数据称为变量,即数据的表现形式为变量。

通常用变量来保存程序执行过程中的输入数据、中间结果和最终结果。

在源程序中,为了区别不同的变量,就需要为变量取一个名字,名字也就是一个标识符,这个标识符就是变量名。在程序运行过程中,通过变量名来访问变量的值。C语言规定,变量在使用之前,必须先定义,定义的位置一般放在函数体的开头。

1. 变量定义的格式

一般来说,变量定义的基本格式为: 


[存储类型]数据类型 变量名1[,变量名2,…,变量名n];

其中,数据类型决定了系统为变量分配的字节数和数的取值范围,变量1、变量2、…、变量n是合法的标识符,即变量名。例如以下定义的变量: 

intx, y, z; 

floatradius, length, area; 

charch;

其中,变量x、y、z定义为基本整型,radius、length、area定义为单精度实型,ch定义为字符型。定义时,可以定义一个变量,也可以同时定义多个变量。

2. 变量的初始化

在定义时,还可以为变量赋初值,称为变量的初始化。例如以下定义的变量: 

int r=3;

其中,定义了变量r为基本整型,同时r的初值为3。

3. 变量的存储地址

在程序运行期间,编译系统会为程序中定义的每个变量分配一定大小的存储单元,存储单元的初始地址称为该变量的存储地址。程序员在编写程序过程中要引用变量的存储地址时,可以通过取地址运算符(&)来获得,引用格式为: 


&变量名

例如以下语句: 

scanf("%lf",&r);

其中,scanf表示从标准输入设备(键盘)输入一个双精度类型的数据存入到变量r所对应的存储单元中,因此,就需要知道r所对应的存储单元地址&r。

 3.3基本数据类型

本节主要讨论以下问题。

(1) 基本数据类型有哪些?

(2) 不同基本数据类型的常量如何表示?

(3) 不同基本数据类型的变量如何定义?定义之后,其占用的存储空间、表示的范围是什么?

(4) 不同基本数据类型的数据在内存中如何存储?

(5) 字符串常量怎么表示?字符串常量与字符常量有什么区别?

使用一个数据时,不但要知道它的表现形式还要知道它的类型。前面介绍到,数据在程序执行过程中,根据其值是否可以改变分为常量和变量,而基本数据类型分为整型、实型、字符型,因此,基本数据又可以分为整型常量、实型常量、字符型常量以及整型变量、实型变量、字符型变量。下面详细介绍基本数据类型的常量和变量的表示及表示范围。



视频讲解


3.3.1整型数据
1. 整型常量的表示形式

整型常量即整型常数。在C语言中,整型常量的表示形式有以下3种。

(1) 十进制整型常量。由数字0~9和正负号组成,如10、-200、897等是合法的十进制整型常量,而056、23F是不合法的十进制整型常量,其中056含有前导0,23F中含有不合法的字母F。

(2) 八进制整型常量。由数字0~7组成,且以数字0开头,如056、071等是合法的八进制整型常量,而086、54是不合法的八进制整型常量,其中086含有不合法数字8,54不是以0开头。

(3) 十六进制整型常量。由数字0~9、字母A~F或a~f组成,且以0X或0x开头,如0x12、0x1ab等是合法的十六进制整型常量,而7B、0X34H是不合法的十六进制整型常量,其中7B不是以0X或0x开头,0X34H中含有不合法的字母H。

2. 整数在内存中的表示

通过第1章的学习,已经了解到数据以二进制形式存储在计算机中,其机内表示形式通常有3种,即原码、反码和补码。其中补码可以连同符号位一起参与运算。因此,计算机系统规定: 整数的数值在内存中用补码的形式存放。在TC 2.0或BC 3.1下,一个整数默认情况下需要2字节(16位)的内存单元存放; 而在DevC++ 6.3、VC++6.0下,则需要4字节(32位)。下面通过具体的例子来观察不同进制整数在内存中的表示形式。

1) 十进制整数

(1) 设有十进制整数17,根据求补码的规则得出17在内存中的表示形式。

① 若用16位的内存单元存放该整数,结果为(17)补=0000 0000 0001 0001。左边第1个数位为符号位。根据数据在内存中的存放位置是高字节放在高地址的存储单元中、低字节放在低地址的存储单元中的原则,可以得出十进制整数17存放在16位的存储单元中的存放形式,如图32所示。

② 若用32位的内存单元存放该整数,结果为(17)补=0000 0000 0000 0000 0000 0000 0001 0001。左边第1个数位为符号位。其在内存中的存放形式如图33所示。



图32十进制整数17存放在16位的
存储单元中的存放形式




图33十进制整数17存放在32位的
存储单元中的存放形式



(2) 设有十进制整数-17,根据求补码的规则得出在内存中的表示形式。

① 若用16位的内存单元存放该整数,结果为(-17)补=1111 1111 1110 1111。左边第1个数位为符号位。其在内存中的存放形式如图34所示。

② 若用32位的内存单元存放该整数,结果为(-17)补=1111 1111 1111 1111 1111 1111 1110 1111。左边第1个数位为符号位。其在内存中的存放形式如图35所示。



图34十进制整数-17存放在16位的
存储单元中的存放形式




图35十进制整数-17存放在32位的
存储单元中的存放形式



2) 八进制整数

(1) 设有八进制整数052,根据不同进制数之间的转换方法及求补码的规则得出下面的结果。

(052)8=(101010)2,则若用16位的内存单元存放该数,结果为(052)补=0000 0000 0010 1010。若用32位的内存单元存放该数,结果为(052)补=0000 0000 0000 0000 0000 0000 0010 1010。

(2) 设有八进制整数-052,根据不同进制数之间的转换方法及求补码的规则得出下面的结果。

若用16位的内存单元存放该数,结果为(-052)补=1111 1111 1101 0110。若用32位的内存单元存放该数,结果为(-052)补=1111 1111 1111 1111 1111 1111 1101 0110。

3) 十六进制整数

设有十六进制整数0X85AB,(0X85AB)16=(1000 0101 1010 1011)2,根据不同进制数之间的转换方法及求补码的规则得出下面的结果。

(1) 若用16位的内存单元存放该数,结果为(0X85AB)补=1000 0101 1010 1011。因此,数据0X85AB在内存中的存放的形式为1000 0101 1010 1011。从该形式中可以看出,最高位为1,说明该数为负数且为其真值的补码在内存中的存放形式,其对应的真值二进制数为-111 1010 0101 0101,即十进制数-31317。

(2) 若为32位的内存单元存放该数,结果为(0X85AB)补=0000 0000 0000 0000 1000 0101 1010 1011。因此,数据0X85AB在内存中的存放的形式为0000 0000 0000 0000 1000 0101 1010 1011。从该形式中可以看出,最高位为0,说明该数为正数且为其真值的补码在内存中的存放形式,其对应的真值二进制数为1000 0101 1010 1011,即十进制数34219。

3. 整型变量

C语言中,当处理的数据以变量的形式出现时,必须先定义后使用。

(1) 整型变量的定义。定义整型变量的基本格式为: 


整型类型名变量名1[,变量名2,…,变量n];

在使用此格式定义整型变量时,必须遵守以下规则。

① 整型类型名属于关键字,必须小写。

② 整型类型名与变量名之间要有空格分开。

③ 可以同时定义多个变量,但变量名间要用“,”分开。

④ 在定义变量时也可以对变量赋初值,具体格式为: 


整型类型名变量名1=值1[,变量名2=值2,…,变量n=值n];

⑤ 最后以“;”结尾。

例如: 

inta;/*定义整型变量a*/

inta,b,c;/*定义整型变量a、b、c*/

inta=3,b;/*定义整型变量a、b,同时给变量a赋初值3*/

inta=3,b=4;/*定义整型变量a、b,同时给变量a、b分别赋初值3、4*/

(2) 整型变量的类型。整型变量的基本类型标识符是int。C语言还允许编程者在定义整型变量时,在int前面加上修饰符,这些修饰符可以是unsigned(无符号)、signed(有符号,可以省略)以及short(短)和long(长)。这样,整型变量的类型就有6种。不同的类型决定了该数的范围以及在内存中占有的空间大小。

例如: 

long int a;

该定义表示定义了一个长整型变量a,在程序执行时为变量a分配4字节。

不同整型变量的类型所表示的数的范围及分配的字节数如表31所示([]表示此部分在定义时可省略,不同类型所占的字节数是指在DevC++ 6.3环境下的取值)。


表31整型变量的类型


类型种类保留字字节数取 值 范 围


整型
有符号基本整型[signed] int4-2147483648~+2147483647

有符号短整型[signed] short [int]2-32768~+32767
有符号长整型[signed] long [int]4-2147483648~+2147483647
无符号基本整型unsigned [int]40~4294967295
无符号短整型unsigned short [int]20~65535
无符号长整型unsigned long [int]40~4294967295


例如: 

int a;/*定义一个有符号基本整型变量a*/

unsigned int a =8;/*定义一个无符号基本整型变量a,并赋初值8*/ 

unsigned a = -20;/*定义一个无符号基本整型变量a,并赋初值-20 */

short int a =10;/*定义一个有符号短整型变量a,并赋初值10 */

unsigned long a = 2;/*定义一个无符号长整型变量a,并赋初值2 */

long a = 245968;/*定义一个有符号长整型变量a,并赋初值245968*/

实际上,不管是哪种类型的数据,它们在计算机内存中都以其补码形式表示,当把数的最高位当成符号位时,则为有符号数; 当把最高位当成数据位看待时,则变为无符号数。 

例如: 

unsigned int a = -2; 

printf("%d",a);/*有符号输出,则为-2 */

printf("%u",a);/*无符号输出,则为4294967294*/

4. 整型常量的类型

整型变量的类型有6种,那么整型常量的类型是不是也有6种呢?C语言根据整型常量的值来决定整型常量的类型,具体判定规则如下。

(1) 根据常量值所在范围确定其数据类型。在TC 2.0或BC 3.1下,若整型常量的值为-32768~32767,C语言则认为它是int型常量; 若整型常量的值为-2147483648~2147483647,C语言则认为它是long型常量。

(2) 长整型。整型常量后加字母l或L,C语言认为它是long int型常量。如483L、571。

(3) 无符号整型。整型常量后加字母u或U,C语言认为它是unsigned int型常量; 加字母ul或UL,则表示是无符号长整型(unsigned long int)常量,如5846UL、5874789012ul。



视频讲解


3.3.2实型数据
1. 实型常量的表现形式

实型也称为浮点型。实型常量也称为实数或者浮点数。在C语言中,实数只采用十进制表示。它用十进制小数和十进制指数两种形式表示。

(1) 十进制小数形式。十进制小数形式表示的实型数据由数字0~9和小数点组成,如0.83、36.12、85.0等。当小数点前面只有0或者后面只有0时,0则可以省略,但小数点不可以省略,如.83、85.等。

(2) 指数形式。十进制指数形式表示的实型数据是由十进制数、阶码标志(e或E)以及阶码组成。其一般形式为aE(e)±n,其中a为十进制数,又称为尾数部分,n为十进制整数,又称为指数部分,两者必不可少; ±表示指数的正负,当指数为正时,+号可以省略。数学中表示为a×10±n。如: 3.2×105可以写成3.2E+5、0.32E+6等合法的指数形式。

可见,实型数据3.2×105可用多种不同的指数形式表示。为了统一起见,C语言中定义了一种标准化的指数形式。标准化的指数形式是E或e之前的尾数部分的小数点左边为零且右边第1位为非零的数字,如30.75的标准化指数形式为0.3075e2。这种标准化的指数形式主要用于存储,提高数据的精确度。但在以指数形式输出时,一般使用规范化的指数形式。规范化的指数形式是指E或e之前的尾数部分的小数点左边第1位为非零的数字,如30.75的规范化指数形式为3.075e+1。

2. 实数在内存中的表示

计算机中的实数按指数形式存放。通常一个实数需要4字节的内存,计算机将这32位分成S、E和M三部分: 最高位S是尾数的符号位,其余的31位分成E和M两部分,E部分用来存放实数的阶码部分,M部分用于存放实数的尾数部分,如图36所示。



图36实数的存储格式


在C语言中,具体如何分配由C语言的编译器来决定。按照IEEE 754标准,常用浮点数的存储分配格式如表32所示。


表32常用浮点数的存储分配格式


符号位S阶码E尾数M总位数


单精度浮点数182332
双精度浮点数1115264
长双精度浮点数1156480


对于浮点数来说,尾数部分占的位数越多,它所能表示的精度越高; 阶码部分占的位数越多,它所能表示的值越大。

【例32】将十进制数78.125表示成机器内的32字节的二进制数形式。

计算方法如下: 

(1) 将78.125表示成二进制数。

(78.125)(10)=(0.78125×102)(10)

则

尾数(0.78125)(10) =(0.11001000000000000000000)(2)

阶码(2)(10) =(00000010)(2)

(2) 根据此过程可以得出符号位、尾数和阶码。

① 符号位: 该数为正数,故第31位为0,占一个二进制位。 

② 阶码: 从第30位到第23位,共占8个二进制位。

③ 尾数为小数点后的部分0.78125,即11001。因为尾数共23个二进制位,在后面补18个0,即11001000000000000000000。

所以,78.125以32字节存储在内存中的存放方式如表33所示。 


表3378.125以32字节存储在内存中的存放方式



符号位(共1位,第31位)阶码(共8位,第30位至第23位)尾数(共23位,第22位至第0位)

00000 00101100 1000 0000 0000 0000 000


3. 实型变量

实型变量有单精度类型、双精度类型和长双精度类型3种。这3种类型对应的标识符分别是float、double、long double。实型变量的定义格式与整型变量的定义格式一样,只是数据类型标识符不同。

例如: 

float r;/*定义1个单精度类型的实型变量r */

double r,c,s;/*定义3个双精度类型的实型变量r、c、s */

float r=3,c,s;/*定义3个单精度类型的实型变量r、c、s,同时变量r赋初值3*/

不同实型变量的类型所表示的数的精度及分配的字节数,如表34所示。


表34实型变量的类型



类型种类保留字字节数精确表示的数字个数


实型
单精度类型float46~7
双精度类型double815~16
长双精度类型long double1618~19


4. 实型常量的类型

实型常量的类型有单精度类型和双精度类型两种。所有的实型常量都按照double类型处理,若要表示单精度类型,则在数值后面加个F或f,如0.12f。

3.3.3字符型数据

有了整型数据和实型数据,就足够处理数学计算了。实际上,计算机除了处理一般的数值信息外,还要处理其他大量的非数值信息,如文本信息。那么,计算机是怎么处理文本信息的呢?字符型数据就是用来表示那些非数值信息的文本数据,如英文字母、符号、汉字等。

字符型数据本质上是整型数据,在内存中存储该字符数据的ASCII且分配1字节的存储单元。下面介绍字符型常量和变量。

1. 字符型常量

字符常量有下面两种表示方法。

(1) 用一对单引号将一个直接输入的字符引起来。直接输入的字符是指通过键盘直接输入的字符。如'a'、'b'和'?'等都是合法的字符常量。

(2) 使用转义字符。对于那些无法直接输入的字符以及某些特殊的字符,需要用由一对单引号括起来的转义字符来表示。转义字符是一种特殊的字符常量,具有特定的含义,不同于原有字符的意义,故称为转义字符。所有的转义字符都以“\”开头,后面跟一个字符或多个数字。C语言中常用的转义字符及其含义如表35所示。


表35常用的转义字符及其含义



形式转 义 字 符含义

\字母
\a响铃
\n换行,光标移到下一行的开头
\r回车,光标移到本行的开头
\t水平制表,跳到下一个制表位(Tab)位置
\f换页,光标移到下页的开头
\b退格,将光标移到前一列
\0空字符,作为字符串的结束标记

\符号
\\代表一个反斜杠字符
\'代表一个单撇号字符
\"代表一个双撇号字符

\数字\ddd代表一个字符,其中ddd是这个字符ASCII码的八进制形式
\字母数字\xhh代表一个字符,其中hh是这个字符ASCII码的十六进制形式

2. 字符型变量

字符型变量的定义格式与其他类型变量的定义格式一样,只是数据类型标识符不同。字符型变量的类型标识符为char。

例如: 

char a;/*定义一个字符型类型的变量a */

char a,b,c;/*定义3个字符型类型的变量a、b、c */

char a='A',b,c;/*定义3个字符型变量a、b、c,同时变量a赋初值'A'*/

3. 字符数据在内存中的表示

在内存中,一个字符型数据占用1字节(8位),以其ASCII码的二进制形式存放。这个ASCII码值就是一个无符号整数,其形式与整数的存储形式一样,所以C语言允许字符型数据与整型数据之间通用。

因此,对一个字符型的变量,可以赋予一个字符常量,也可以赋予一个整数。在输出一个字符型数据时,可以以字符格式输出,也可以整数格式输出。若以字符格式输出时,系统自动将存储单元中的ASCII码转换为字符,然后输出; 若以整数格式输出时,系统直接将其ASCII码作为整数输出。 

【例33】转义字符的使用。

源程序: 



1/*3-3.c*/

2#include <stdio.h>

3int main ( )

4{

5printf ("\101\t\x42\tC\n");

6printf ("\"Hello\"\n");

7printf ("\\C Program\\\n");

8return 0;

9}






程序解析: 

该程序函数体共有4行,主要由函数printf完成信息的输出。

第5行“printf ("\101\t\x42\tC\n");”中,包含转义字符\101、\t、\x42和\n,根据常用转义字符表中描述的意义,分别表示字符'A'、制表符、'B'和换行。

第6行“printf ("\"Hello.\"\n");”中,包含转义字符'\"'、'\n',分别表示字符双引号"和换行。

第7行“printf ("\\C Program\\\n ");”中,包含转义字符\\、\n,分别表示字符'\'和换行。

因此,根据以上分析,程序运行结果如下。

ABC

"Hello."

\C Program\

【例34】字符型数据和整型数据通用。

源程序: 



1/*3-4.c*/

2#include"stdio.h"

3int main()

4{

5int x,y;

6char c1,c2;

7x='a';/*字符常量赋给整型变量*/

8y='b';

9c1=97;/*整型常量赋给字符变量*/

10c2=98;

11c1=c1-32;/*字符变量进行算术运算*/

12c2=c2-32;









13printf("%d %d\n",x,y);/*整型变量以整型格式输出*/

14printf("%c %c\n",x,y);/*整型变量以字符型格式输出*/

15printf("%c %c\n",c1,c2);/*字符型变量以字符型格式输出*/

16printf("%d %d\n",c1,c2);/*字符型变量以整型格式输出*/

17return 0;

18}






程序解析见程序后面的注释,以第13行为例,表示输出两个整型变量x和y,都以%d的形式输出,即以十进制整型输出,虽然x和y赋值为字符型,但x和y的结果是这两个字符'a'和'b'对应的ASCII码。该程序运行结果如下。

97 98

a b

A B

65 66

3.3.4字符串常量
1. 字符串常量的定义

C语言规定,由一对双引号括起来的字符序列称为字符串常量。如"123"、"abc456"、" "(空字符串)等都是合法的字符串常量。

字符串中字符的个数称为字符串长度。长度为0的字符串(即一个字符都没有的字符串)称为空串,表示为" "(一对紧连的双引号)。例如,"How do you do."、"Good morning."等,都是字符串常量,其长度分别为14和13。

若字符串常量中出现反斜杠和双引号作为字符串中的有效字符,则必须以转义字符给出。例如: 字符串C:\program\chap3 则应写成"C:\\program\\chap3"的形式。

2. 字符串在内存中的表示




图37字符串"China"在内存
中的存储形式

C语言规定: 在存储字符串常量时,由系统在字符串的末尾自动加一个'\0'作为字符串的结束标志。例如字符串"China"在内存中的存储形式如图37所示。

综上所述,字符常量'A'与字符串常量"A"有三点区别。

(1) 定界符不同。字符常量使用单引号; 而字符串常量使用双引号。

(2) 长度不同。字符常量的长度固定为1; 而字符串常量的长度是≥0的整数。

(3) 存储要求不同。字符常量存储字符的ASCII码值; 而字符串常量,除了要存储有效的字符外,还要存储一个结束标志'\0'。

 3.4常用运算符与表达式

本节主要讨论以下问题。

(1) C语言中常用的运算符有哪些?这些运算符按照操作对象的个数不同可以分为哪些类型?按照功能来分,又分为哪些类型?

(2) 算术运算符的功能是什么?算术运算符有哪些?其优先级和结合性怎样?什么是算术表达式?如何计算算术表达式?

(3) 自增自减运算符的功能是什么?自增自减运算符有哪些?其优先级和结合性怎样?

(4) 赋值运算符的功能是什么?赋值运算符有哪些?其优先级和结合性怎样?什么是赋值表达式?如何计算赋值表达式?

(5) 类型转换的原理是什么?自动类型转换的规则是什么?强制类型转换运算符的功能是什么?如何使用强制类型转换运算符?其优先级怎样?

(6) 逗号运算符的功能是什么?其优先级和结合性怎样?什么是逗号表达式?如何计算逗号表达式?

(7) sizeof运算符的功能是什么?其优先级和结合性怎样?如何计算值?

(8) 位运算符的功能是什么?位运算符有哪些?其优先级和结合性怎样?什么是位运算表达式?如何计算位运算表达式?

变量用来存放数据,运算符则用来处理数据。用运算符将变量和常量连接起来的符合C语言语法规则的式子称为表达式。这些常量和变量称为运算符的操作数,每个表达式都有一个值。在以后的章节中,将陆续介绍C语言支持的运算符和表达式。

C语言提供了丰富的运算符。根据运算符所需要操作数的个数,可以把运算符分成以下3种类型。

(1) 单目运算符: 运算时,需要一个操作数的运算符。

(2) 双目运算符: 运算时,需要两个操作数的运算符。

(3) 三目运算符: 运算时,需要三个操作数的运算符。



图38C语言的运算符


在C语言中,运算符和表达式相当丰富,数量繁多。在表达式的计算中,不仅要考虑运算符的优先级,还要考虑同一优先级的运算符具有的结合性。因此对于运算符的学习,可以从运算符的功能、与运算量的关系、运算符的优先级、运算符的结合性以及运算结果的类型5方面进行学习和掌握。

C语言提供了13类运算符,如图38所示。

C语言规定了运算符的优先级和结合性。结合性是C语言的独有概念。所谓结合性是指,当一个操作数两侧的运算符具有相同的优先级时,该操作数是应该与左边的运算符结合,还是应该与右边的运算符结合。若是自左至右的结合方向,称为左结合性;  反之,称为右结合性。除单目运算符、赋值运算符和条件运算符是右结合性外,其他运算符都是左结合性。

下面介绍最常用的算术运算符、赋值运算符、强制类型转换运算符、求字节长度运算符、逗号运算符、位运算符及其表达式,其他运算符将在以后的章节中陆续介绍。


视频讲解


3.4.1算术运算符及其表达式
1. 算术运算符

C语言提供的算术运算符的功能是进行加、减、乘、除四则运算,算术运算符主要包括5种: 加(+)、减(-)、乘(*)、除(/)和取余(%)。

算术运算符都是双目运算符,*、/、%优先级相同且高于优先级相同的+、-。此外,+、-、*、/可用于任何数据类型间的算术运算,而%只能用于整型数据的算术运算。例如,5%2的值为1,5/2的值为2,5.0/2的值为2.5,5.0%2则是不合法的表达式。因此,C语言规定,两个整数相除(/),其商为整数,否则与数学运算保持一致。

2. 表达式和算术表达式

用运算符将运算对象连接起来、符合C语言语法规则的式子,称为表达式。运算对象可以是常量、变量、函数或其他表达式。单个常量、变量或函数,可以看作表达式的特例。将单个常量、变量或函数构成的表达式称为简单表达式,其他表达式称为复杂表达式。 

若表达式中的运算符都是算术运算符,称为算术表达式。例如,3+14、56*17%10都是合法的算术表达式。

3. 算术运算符的优先级和结合性

在计算算术表达式值时,必须考虑其运算符的优先级和结合性,先乘、除和取余,再加、减,同级运算符的计算顺序是从左到右,即左结合性。例如,在计算a-b+c时,先执行a-b; 然后执行加c的运算。 

3.4.2自增自减运算符、负号运算符

C语言中,减号(-)是一个算术运算符,其实也是一个负号运算符。负号运算符是一个单目运算符。例如,a=-5,-a的值则为5。

C语言还提供了两个用于算术运算的运算符: 自增(++)和自减(--)运算符。自增、自减运算符属于单目运算符,它们的结合性为右结合性。这两个运算符的优先级比其他5个算术运算符(加、减、乘、除、取余)的优先级高。

1. 作用与用法

自增(++)运算符的作用是使单个变量的值增1,自减(--)运算符的作用是使单个变量的值减1。在使用时,自增(++) 和自减(--) 运算符只可以放在变量之前或之后,不能放在常量和表达式的前或后。例如,10++、--(x+y)等都是非法的。

自增自减运算符常用于循环语句中,使循环变量增1或减1,还用于指针变量中,使指针下移(或上移)一个存储单元。例如,若对变量a进行增1,可以写成++a或a++; 若对变量a进行减1,可以写成--a或a--。

2. 运算规则

(1) 前置运算。自增(++)和自减(--)运算符放在变量之前称为前置运算。例如,++a和--a。此时,运算规则为表示变量自身先加或减1,然后使用变量运算后的值参与其他运算。

例如: 

int a=5,b;

请分析下面表达式执行完后a、b的值。

b=++a

此表达式中有两个运算符++和=,++放在a之前,因此,a先加1的值为6,再参与=运算,将a的值6赋给b,则b的值为6。此执行过程等价于以下两个表达式: a=a+1,b=a。

(2) 后置运算。自增(++)和自减(--)运算符放在变量之后称为后置运算。例如: a++和a--。此时,运算规则为先使用变量的原值参与其他运算,结束之后变量自身加1或减1。

【例35】自增、自减运算符的用法。

源程序: 



1/*3-5.c*/

2#include"stdio.h"

3int main()

4{

5int x=6, y;

6printf("x=%d\n",x);

7y=++x;

8printf("x=%d,y=%d\n",x,y);

9y= x--;

10printf("x=%d,y=%d\n",x,y);

11return 0;

12}






程序解析: 

(1) 程序中第7行表达式语句“y=++x;”中有两个运算符: ++和=。++放在x之前,因此先执行++运算,即x自身加1等于7,然后将x的值赋给y,y的值为7。此执行过程等价于以下两个表达式: x=x+1,y=x。

(2) 程序中第9行表达式语句“y=x--;”中有两个运算符: --和=。--放在x之后,因此先执行=运算,即将x的值赋给y,y的值为7,然后执行--运算,即x自身减1等于6。此执行过程等价于以下两个表达式: y=x,x=x-1。

根据以上分析过程,该程序的运行结果如下。

x=6

x=7,y=7

x=6,y=7

3.4.3赋值运算符及其表达式
1. 赋值运算符

赋值符号“=”就是C语言中的赋值运算符,它的作用是将一个表达式值赋给一个变量。赋值运算符是双目运算符,它的优先级比算术运算符、自增自减运算符的优先级低,是右结合性。

2. 赋值表达式

由赋值运算符将一个变量和一个表达式连接起来的表达式,称为赋值表达式。它的一般格式是: 


变量=表达式

注意,赋值运算符“=”的左侧只能是变量,右侧可以是变量、常量、函数调用或其他复杂表达式。功能是将表达式值赋给变量。

若表达式值的类型与被赋值变量的类型不一致,系统会自动地将表达式值转换成被赋值变量的数据类型,然后赋值给变量。

例如: 

int a,b,c;

a=30;

b=a+10;

c=a+b/10;

3. 赋值语句

C语言规定,赋值表达式末尾加上分号就构成一条赋值表达式语句,简称为赋值语句。例如,“a=30;”“b=a+10;”“c=a+b/10;”就是3条赋值语句。

4. 复合的赋值运算符

复合赋值运算符是由一个双目运算符和“=”结合在一起构成,复合赋值运算符包括+=、-=、*=、/=、%=、=、=、^=、&=、|=。由复合赋值运算符将一个变量和一个表达式连接起来的表达式,称为赋值表达式。它的一般格式是: 


变量op=表达式

此赋值表达式等价于: 


变量=变量op(表达式)

其中,op表示算术或位运算符,当表达式为简单表达式时,表达式外的一对圆括号才可缺省,否则可能出错。

例如: 

a+=10/*等价于a=a+10*/

a*=b+2/* 等价于a= a*(b+2),而不是a=a*b+2*/

5. 赋值表达式的应用

1) 多个变量连续赋值

例如: 

假设有int a, b=5, c=4,求a-=a=b+c表达式的值。

分析:  

此表达式为赋值表达式,且含有多个赋值运算符。按照赋值运算符的右结合性,分为以下两步完成。

(1) a=b+c,将b+c的值9赋给a,因此,a的值为9。

(2) a-=a,等价于a=a-a,将a-a的值为0赋给a,因此,a的值为0。

2) 赋值表达式的嵌套

例如: 

设有表达式a=(b=2)+(c=3),则a=?

分析:  


此表达式为赋值表达式,且含有括号运算符、加法运算符和赋值运算符。由于括号的优先级最高,因此,先计算括号中的表达式,将2赋给b,同理赋值表达式c=3的值为3,然后进行加法运算b+c,值为5,最后将值5赋给a,即a=5。



视频讲解


3.4.4强制类型转换运算符

C语言提供了丰富的数据类型,当不同类型的数据在一起进行运算时,这些数据的类型可以相互转换。转换的方法有两种: 一种是自动类型转换; 另一种是强制类型转换。

1. 自动类型转换

若一个运算符两侧的操作数的数据类型不同,则系统按“先转换、后运算”的原则,首先将数据自动转换成同一类型,然后在同一类型数据间进行运算。

自动类型转换是由机器直接完成的,其转换规则如图39所示。

使用图39的转换规则时,需遵守以下规则。

(1) 图39中的横向左箭头表示必定进行的转换: char和short型数据在参与运算时会自动转换为int型,float型数据在参与运算时会自动转换为double型。

(2) 图39中的纵向短箭头表示int型、unsigned型、long型和double型之间的转换方向。若int型和double型数据进行混合运算,int型数据会自动转换为double型,运算的结果也是double型。

(3) 图39中的纵向长箭头表示转换类型的级别高低,低级别的数据类型会转换成高级别的数据类型,并不表示从下至上依次转换。例如: 

char ch;

int i;

float f;

double d;

那么表达式“result=(ch/i)+(f*d)-(f+i)”的结果类型是哪一种?

分析过程: 

根据图39的转换规则,在表达式result的计算过程中,各操作数类型的转换过程如图310所示。



图39自动类型转换规则





图310在表达式result的计算过程中,
各操作数类型的转换过程



2. 强制类型转换

在进行数据处理时,有时需要把数据类型转换成规定的数据类型或者在赋值时保持左右类型一致,这时可以采用强制类型转换符“()”达到要求。强制类型转换又称为显式类型转换。强制类型转换的一般格式为: 

(类型名)(表达式)

强制类型转换符“(类型名)”中的类型名是指要转换成的目标类型名,表达式是指需要转换的数据对象,数据对象可以是常量、变量或其他更复杂的表达式。当被转换的表达式是一个简单表达式时,圆括号可以缺省。

强制类型转换得到的是一个所需类型的中间量,原表达式类型并不发生变化。例如,(double)a是得到一个将变量a转换成double型的中间值去参与运算,而变量a的数据类型并未转换成double型。

例如: 

int a;

float b;

(float)(a)/*等价于(float)a,得到变量a强制转换成float型的一个值*/

(int)(b)/*等价于(int)b,得到变量b强制转换成int型的一个值*/

(int)(b+a) /*得到表达式(b+a)强制转换成int型的一个值*/

(int)b+a/*得到变量b强制转换成int型的一个值,将这个值与变量a相加,运算结果为int型*/

3.4.5逗号运算符及其表达式

逗号运算符(,)又称顺序求值运算符,是C语言中优先级最低的运算符,具有左结合性。使用该运算符能够将多个表达式连接起来,用逗号连接起来的表达式称为逗号表达式。逗号表达式的一般格式是: 

表达式1,表达式2,…,表达式n

例如: 8,a+4,b=a是一个逗号表达式(假设已定义变量a、b)。

逗号表达式的求值顺序是从左到右依次求取每个用逗号分隔的表达式,最后一个表达式的值就是整个逗号表达式的值。

例如,逗号表达式“(a=3*5,a/5),a+20”的值为35,求解过程如下。

(1) 求a=3*5,得a=15; 

(2) 求a/5=3,但a的值未改变; 

(3) 求a+20=35。

因此,逗号表达式的值为35。

3.4.6sizeof运算符

C语言中提供了一个能获取数据或数据类型所占内存大小的运算符——sizeof,称为求字节长度运算符,是单目运算符。其使用的一般格式是: 


sizeof(数据或数据类型名)

例如: 

double a;

char b;

则表达式sizeof(a)的值为8,sizeof(char)的值为1,sizeof(a+b)的值为8。

3.4.7位运算符及其表达式

位运算是对字节或字节内部的二进制进行测试、设置、移位或逻辑的运算,是C语言的重要特色之一,利用位运算可以实现与硬件密切相关的操作。位运算有两类: 位逻辑运算和移位运算。实现这两种运算的运算符分别为位逻辑运算符和移位运算符,统称为位运算符。运用位运算符将操作数连接起来的式子称为位运算表达式。

1. 位逻辑运算符

位逻辑运算符有~、&、^和|四种,它们的类型、功能、运算规则如表36所示,优先级由高到低依次为~、&、^、|,其中,按位取反运算符~是单目运算符,所以是右结合性,其他三个运算符的优先级相同,且满足左结合性。


表36位逻辑运算符


类型位逻辑
运算符功能操作数1位操作数2位结果运算规则描述


单目~按位取反

01
100按位取反为1,1按位取反为0

双目

&按位与

|按位或
^按位异或

000
010
100
111
000
011
101
111
000
011
101
110
只有两个操作数对应的位均为1时,结果才为1,其他情况均为0
只有两个操作数对应位均为0时,结果才为0,其他情况均为1
两个操作数对应位的值相同时结果为0,否则为1


【例36】令a=10,b=8,c=a&b,求c的值。

00001010(10)

&00001000(8)



00001000(8)



所以c=8。

【例37】令a=12,b=9,c=a|b,求c的值。

00001100(12)

|00001001(9)




00001101(13)



所以c=13。

【例38】令a=10,b=8,c=a^b,求c的值。

00001010(10)

^00001000(8)




00000010(2)



所以c=2。

【例39】a=8,c=~a,求c的值。


^00001000(8)



11110111(245)



所以c=245。

2. 移位运算符

移位运算是指对二进制操作数向左移或向右移的操作。移位运算符有左移()和右移(),它们都是双目运算符,优先级相同,满足左结合性。移位运算的具体实现方式有循环移位、逻辑移位和算术移位。

1) 左移位运算符()

左移位的运算规则是指在移位过程中,操作数的二进制位向左移动,右端空出的位补0,左端移出的位被舍弃。从左移位的规则可以看出,对于无符号数而言,左移n相当于乘以2n。

其语法格式为an,其中a是操作数,可以是整型或字符型的变量或表达式,n是移位的位数,只能是整数。功能是将a中的二进制位数向左移动n位。

例如,a=12,二进制形式为00001100,则a2表示将各个二进位顺序左移2位,得到00110000,即十进制数48。

2) 右移位运算符()

右移位的运算规则是指在移位过程中,操作数的二进制位向右移动,左端空出来的位补0或1,右端移出的位被舍弃。这里补0还是补1取决于操作数是有符号数还是无符号数,具体如下。

(1) 对于无符号数向右移时,左端空出端补0。

(2) 对于有符号数向右移时,如果采用逻辑位移,则不管是正数还是负数,左端一律补0; 如果采用算术位移,则正数右移,左端的空位全部补0,负数右移,左端的空位全部补1。Turbo C和DevC++编译采用算术右移。

其语法格式为an,其中a是操作数,可以是整型或字符型的变量或表达式; n是移位的位数,只能是整数。功能是将a中的二进制位数向右移动n位。从右移位的规则可以看出,对于无符号数而言,右移n位相当于除以2n。

例如,a=12,二进制形式为00001100,则a2表示将各个二进制位顺序右移2位,得到00000011,即十进制数3。

3. 复合赋值位运算符

除了位非运算符(~)外,其他位运算符均能和赋值运算符“=”结合起来构成复合赋值运算符,它们是: &=、|=、^=、=、=。

例如,对于a=5,b=4,则有: 

(1) a&=b等价于a=a&b=5&4=101&100=100=4。

(2) a|=b等价于a=a|b=5|4=101|100=101=5。

(3) a^=b等价于a=a^b=5^4=101^100=001=1。

(4) a=2等价于a=a2=52=1012=1。

(5) a=2等价于a=a2=52=1012=10100=20。

4. 位运算的特殊用途

通过位运算符可以实现一些特殊操作,如位与运算可以将操作数置零、取操作数中的某些位和将操作数的某些位保留,位或运算可以将操作数的某些位变为1,位异或操作可以将操作数的特定位置反、保留原值。

【例310】已知a=80,用位运算符实现以下操作: 

首先,将a变成0。

然后,将a的3~5位置1,其他位不变。

最后,将a的低4位置反,其他位不变。

a所对应的二进制为01010000,分析过程如下。

首先,将a变成0,根据位与运算规则,只要找到一个操作数,这个操作数具有以下特点: 原数中为1的位,操作数中对应的位为0,操作数的其他位可以是0和1中的任何情况,然后将两个数进行与运算。下面就是其中一种操作过程: 

01010000(80)

&00001001(9)





00000000(0)



然后,将a的3~5位置1,其他位不变。根据位或运算规则,只要找到一个操作数,这个操作数满足以下特点: 与原数这些位对应的操作数相应位为1,其他位为0,然后将两个数进行或运算。操作过程如下: 

01010000(80)

|00111000(56)




01111000(120)



最后,将a的低4位置反,其他位不变。根据位异或运算规则,只要找到一个操作数,这个操作数满足以下特点: 与原数低4位对应的操作数相应位为1,其他位为0,然后将两个数进行异或运算。操作过程如下: 

01010000(80)

^00001111(15)




01011111(95)



 3.5常见数学运算表达式在C语言中的表示

本节主要讨论以下问题。

常见数学运算表达式在C语言中正确表达应该注意哪些问题?

在进行数据处理时,有很大一部分表达式是数学表达式。若选择C语言程序设计,就需要借助C语言丰富的运算符,将此数学表达式转换为C语言支持的表达式进行计算,才能得到正确的结果。转换规则如下所述。

1. 基本符号的变化

(1) 在C语言中,表达式的乘号不能省略。

(2) 数学中的分数符号“-”要改成C语言中的除号“/”。在转换成“/”时,要注意分子和分母的类型,必要时要进行类型转换,才能保证最终结果的等价性。如分式25直接转换成2/5就会出问题,因为前者的结果是0.4,后者的结果为0,所以此时要进行类型转换,可以写成2.0/5或者(float)2/5。

(3) 数学中的“≤”号要改成C语言中的“<=”号。

(4) 数学中的π和e是个常值,但在C语言中不能直接写π和e,必须将它们的值直接写出或者将其定义为符号常量。

(5) 在C语言中,平方根不能直接使用,需要借助C中的库函数sqrt。

(6) 数学中的绝对值“||”符号,也不能直接使用,需要借助C中的库函数abs或者fabs。

例如: 

① 圆面积公式s=πr2,对应的C语言表达式为s=3.14*r*r。

② 球体积公式v=43πr3,对应的C语言表达式为v=4.0/3*3.14*r*r*r。

2. 借助库函数

除了基本符号的变化外,还有一些特殊符号,如根号、数的多次方、绝对值或者正弦、余弦等,若表达式出现了这些符号或运算时,就需要使用C语言提供的库函数。当程序中用到了C语言提供的库函数时,就需要告知程序这些库函数来自哪个头文件。像刚才提到的根号、绝对值和三角函数等,它们都需要使用头文件“math.h”中的相关数学库函数,因此,需要将文件包含预处理命令#include "math.h"放在程序开头。具体C语言提供的库函数参见附录E。例如: 

(1) a对应的C语言表达式为sqrt(a)。

(2) sin60°对应的C语言表达式为sin(60*3.1415926/180)。

(3) int a,b;|a+b|对应的C语言表达式为abs(a+b)。

(4) a3对应的C语言表达式为a*a*a。

(5) xy对应的C语言表达式为pow(x,y)。

 3.6本章小结
3.6.1知识梳理

本章所介绍的主要内容是C语言中的基本数据类型,即整型数据、实型数据和字符型数据的常量和变量,以及作用于这些数据类型的基本运算符及其表达式,即算术运算符及其表达式、自增自减运算符和负号运算符、赋值运算符及其表达式、强制类型转换运算符、逗号运算符及其表达式、sizeof运算符和位运算符及其表达式。

本章的内容比较繁杂,学起来比较枯燥,但本章的内容是学好C语言的基础,每个C语言程序员必须熟练掌握。在学习的过程中,不必过分强求记住每一个细节,可以在后续写程序的过程中遇到了再到本章来查阅相关需要注意的问题。这样,学习的目的性就更强,也更容易明白之前学习的意义,也就能更快更好地记住和掌握。本章知识导图如图311所示。



图311本章知识导图


3.6.2常见上机问题及解决方法
1. 使用未定义的变量

C语言要求变量必须先定义,后使用。

例如: 

#include "stdio.h" 

int main()

{

a=1;b=a+2;/*a,b 未定义*/

printf("%d,%d",a,b);

return 0;

}

2. 一行C语句后面漏掉“;”

C语言要求每一条语句都要以“;”结尾,但在输入程序过程中常常会漏掉末尾的分号,特别是在使用++、--时。

例如: 

#include "stdio.h"

int main()

{

int a;/*以下3 条语句都漏掉了“;”*/

scanf("%d",a)

a++

printf("%d",a)

return 0;

}

3.语序颠倒

表达式在进行计算时,要确保相应操作数都有确定的值,也就是有些变量被定义后,需要赋初值才能开始使用。因此,下面的程序输出的结果不是5。

#include "stdio.h"

int main()

{

int a,b;

a=b+4;/* b没有赋初值 */

b=1;

printf("%d",a);

return 0;

}

4. 混淆字符常量和字符串常量

C语言中字符常量用一对单引号引起来,而字符串常量用一对双引号引起。例如: 'A'表示字符常量,而"A"则表示字符串常量。字符常量只能赋值给字符型变量,而字符串常量只能赋值给字符数组字符型指针或利用strcpy复制到字符数组中。

例如: 

char ch,str[10];

char *p;

ch='M';

p="12345";

strcpy(str,"abcd");

/*以下语句则是错误的*/

ch="A";

p='1';

5. 定义变量时漏掉“;”

C语言中变量定义的格式是“类型标识符 变量名1[,变量名2,…,变量名n];”。但初学者常常在定义变量时,漏掉变量名后面的分号,尤其是同时定义多个变量时更是如此。

例如: 

#include "stdio.h"

int main()

{

int a,b,c /*连续定义3个变量,却忘记了“;”*/

a=2;

b=a*a;

c=b*a;

printf("%d",c);

return 0;

}

6. 定义变量时数据类型关键字与变量名之间无空格

在输入程序时很容易漏掉类型标识符与变量名之间的空格。下面定义变量的方式是错误的。

inta,b;/*int和a之间没有空格*/

7. 对表达式进行强制类型转换时漏掉了“()”

在进行强制类型转换时,通常要将表达式和类型标识符都用“()”括起来。例如,(int)(f*10/21)表示将f*10/21的结果转换为int型。若漏掉了表达式的“()”,则变成了(int)f*10/21,这样就表示先将f转换为int型再乘以10除以21,其结果与(int)(f*10/21)可能会不一样。

此外,如果强制类型转换运算符漏掉了类型标识符的“()”,便会出现语法错误,在编译时不能通过,例如“k=int(f*10/21);”是错误的。 

8. 用'\'表示\

C语言中字符“\”是转义控制字符引导符,在C语言编译器对字符“\”的解释要看“\”后面跟的是什么字符,如果是“\n”,则表示换行; 如果是“\'”,则表示字符单引号。但是,表示字符“\”就要用“'\\'”。

当字符串包含转义字符时,就要注意字符串的长度。例如,字符串"ab12\0245\d\\"的长度为8,这8个字符分别是: 'a'、'b'、'1'、'2'、'\024'、'5'、'\d'和'\\'。

9. 使用关键字作为变量名

C语言中关键字都有各自的特殊用途。例如,int表示整型类型,用来定义整型变量; break用于跳出循环语句或switch语句。但是,初学者有时为了给变量取一个有意义的名字而又想不起其他更好的英文单词时,就会不经意地使用这些关键字来为变量取名。例如: 

int break , int;/* 关键字break和int 都不能作为变量名 */

 习题3

1. 如下变量在内存中的地址如何引用?

abcsumaverage

2. 下列哪些是整型常量?

7890870x34584a0234234

3. 下列哪些是实型常量?

8.121..12123.12311E22.e+33.34e35.4e9.9e464.235e

4. 下列哪些是字符常量?

'a''ab''b''? ''2''\234''\x23''\25''\x3a'

5. 下列数据在内存中分别占多少字节?

int a;long b;char c;double d;"234""\234mnox"

6. 假设有以下定义: 

int a;float b;char c; 

下列表达式结果分别是什么类型?

① a+b② b+c③ (int)c+b④ (int)(b+c)

7. 求下列表达式分别执行完后,变量a、b的值分别是多少(假设a的初值是8)?

① b=--a;

② b=a--;

8. 下列各表达式的值是多少?

int a=5,b=9,c=7;

char d='A';

float e=2.0,f=1e1;

① b/a② b%c③ c/f④ a+b-e

9. 计算下列赋值表达式的值(a、b的值分别为6和5)。

① a=b② a+=b③ a+=b*=a④ a-=a/b

10. 选择题

(1) 以下叙述中错误的是()。

A. 用户所定义的标识符允许使用关键字

B. 用户所定义的标识符应尽量做到“见名知意”

C. 用户所定义的标识符必须以字母或下画线开头

D. 用户定义的标识符中,大、小写字母代表不同标识

(2) 以下叙述中错误的是()。

A. C语句必须以分号结束

B. 复合语句在语法上被看作一条语句

C. 空语句出现在任何位置都不会影响程序运行

D. 赋值表达式末尾加分号就构成赋值语句

(3) 以下能正确定义且赋初值的语句是()。



A. int n1=n2=10;B. char c=32;

C. float f=f+1.1;D. double x=12.3E2.5;

(4) 以下选项中可作为C语言合法常量的是 ()。

A. -80.B. -080C. -8e1.0D. -80.0e

(5) 有以下程序

#include "stdio.h"

int main()

{int m=12,n=34;

printf("%d%d",m++,++n);

printf("%d%d\n",n++,++m);

return 0;

}

程序运行后的输出结果是()。

A. 12353514B. 12353513C. 12343514D. 12343513

(6) 以下符合C语言语法的实型常量是()。

A. 1.2E0.5B. 3.14.159EC. 5E-3D. E15

(7) 若以下选项中的变量已正确定义,则正确的赋值语句是()。

A. x1=26.8%3B. 1+2=x2

C. x3=0x12D. x4=1+2=3

(8) 以下叙述中正确的是()。

A. C语言程序中注释部分可以出现在程序中任意合适的地方

B. 大括号“{”和“}”只能作为函数体的定界符

C. 构成C语言程序的基本单位是函数,所有函数名都可以由用户命名

D. 分号是C语句之间的分隔符,不是语句的一部分

(9) 以下选项中可作为C语言合法整数的是()。

A. 10110BB. 0386C. 0XffaD. x2a2

(10) 下列关于单目运算符++、--的叙述正确的是()。



A. 它们的运算对象可以是任何变量和常量

B. 它们的运算对象可以是char型变量和int型变量,但不能是float型变量

C. 它们的运算对象可以是int型变量,但不能是double型变量和float型变量

D. 它们的运算对象可以是char型变量、int型变量和float型变量

(11) 若有以下程序: 

#include "stdio.h"

int main()

{int k=2,i=2,m;

m=(k+=i*=k);printf("%d,%d\n",m,i);

return 0;

}

执行后的输出结果是()。

A. 8,6B. 8,3C. 6,4D. 7,4

(12) 以下选项中,与k=n++完全等价的表达式是()。

A. k=n,n=n+1B. n=n+1,k=nC. k=++nD. k+=n+1

(13) 以下选项中不属于C语言的类型的是()。

A. signed short intB. unsigned long int

C. unsigned intD. long short

(14) 假定x和y为double型,则表达式x=2,y=x+3/2的值是()。

A. 3.500000B. 3C. 2.000000D. 3.000000

(15) 下列选项中,合法的C语言关键字是()。

A. VARB. cherC. integerD. default

(16) 若a为int类型,且其值为3,则执行完表达式a+=a-=a*a后,a的值是()。

A. -3B. 9C. -12D. 6

11. 程序设计题

(1) 本利计算。小明每年过完春节后定期存入本金capital元,利率为rate,存期为n年,编程帮助小明计算到期时能从银行得到的本利之和deposit。假设利息公式如下: 

利息=capital×rate×n

(2) 整数的算术运算。输入两个整数a和b,分别计算并输出两个整数的和、差、积、商和余数。