即左边级别"低"的类型向右边转换。
具体地说,若在表达式中优先级最高的数据是double型,则此表达式中的其他数据均被转换成double型,且计算结果也是double型;若在表达式中优先级最高的数据是float型,则此表达式中的其他数据均被转换成float型,且计算结果也是float型。
在做赋值运算时,若赋值号左右两边的类型不同,则赋值号右边的类型向左边的类型转换;当右边的类型高于左边的类型时,则在转换时对右边的数据进行截取。
除自动转换外,还有强制转换,表示形式是:
(类型)(表达式);
第2章运算符与表达式
2.1C语言运算符简介
2.1.1C运算符简介
C语言的运算符范围很宽,几乎把所有的基本操作都作为运算符处理,具体运算符见表2-1。
另外,按参与运算的对象个数,C语言运算符可分为:
单目运算符(如!
)、双目运算符(如+,-)和三目运算符(如?
:
)。
2.1.2运算符的结合性和优先级
(1)在C语言的运算符中,所有的单目运算符、条件运算符、赋值运算符及其扩展运算符,结合方向都是从右向左,其余运算符的结合方向是从左向右。
(2)各类运算符优先级的比较:
初等运算符>单目运算符>算术运算符(先乘除后加减)>关系运算符>逻辑运算符(不包括"!
")>条件运算符>赋值运算符>逗号运算符。
说明:
以上优先级别由左到右递减,初等运算符优先级最高,逗号运算符优先级最低。
2.1.3强制类型转换运算符
可以利用强制类型转换符将一个表达式转换成所需类型,其一般形式为:
(类型名)(表达式)
例如:
(char)(x+y);,将(x+y)的值强制转换为字符型。
(double)(m*n);,将(m*n)的值强制转换为double类型。
表达式应用括号括起来,如果写成(char)x+y,则表示只将x转化为字符型,然后与y相加。
2.1.4逗号运算符和逗号表达式
用逗号运算符将几个表达式连接起来,例如a=b+c,b=a*a,c=a+b,称为逗号表达式。
一般形式为:
表达式1,表达式2,表达式3,…,表达式n
逗号表达式的求解过程是:
先求解表达式1,然后依次求解表达式2,直到表达式n的值。
整个逗号表达式的值就是表达式n的值。
需要注意的是,逗号运算符是所有运算符中级别最低的。
2.2算术运算符和算术表达式
2.2.1基本的算术运算符
(1)+(加法运算符或正值运算符,如2+6)。
(2)-(减法运算符或负值运算符,如6-3)。
(3)*(乘法运算符,如2*8)。
(4)/(除法运算符,如6/5)。
(5)%(模运算符或称求余运算符,%两侧均应为整型数据,如9%7的值为2)。
需要说明的是:
两个整数相除的结果为整型,如5/3的结果值为1,舍去小数部分,如果参加+、-、*、/运算的两个数中有一个数为实数,则结果是double类型。
2.2.2算术表达式和运算符的优先级与结合性
算术表达式是用算术运算符和括号将运算量(也称操作数)连接起来的、符合C语言语法规则的表达式。
运算对象包括函数、常量和变量等。
在计算机语言中,算术表达式的求值规律与数学中的四则运算的规律类似,其运算规则和要求如下。
(1)在算术表达式中,可使用多层圆括号,但括号必须配对。
运算时从内层圆括号开始,由内向外依次计算各表达式的值。
(2)在算术表达式中,对于不同优先级的运算符,可按运算符的优先级由高到低进行运算,若表达式中运算符的优先级相同,则按运算符的结合方向进行运算。
(3)如果一个运算符两侧的操作数类型不同,则先利用自动转换或强制类型转换,使两者具有相同类型,然后进行运算。
2.2.3自增自减运算符
作用:
使变量的值增1或减1。
如:
++i,--i(在使用i之前,先使i的值加1、减1)。
i++,i--(在使用i之后,使i的值加1、减1)。
(1)只有变量才能用自增运算符(++)和自减运算符(--),而常量或表达式不能用,如10++或(x+y)++都是不合法的。
(2)++和--的结合方向是"自右向左",如-i++,i的左边是负号运算符,右边是自增运算符,负号运算和自增运算都是"自右向左"结合的,相当于-(i++)。
在循环语句中常用到自增(减)运算符,在指针中也常用到该运算符,考生要弄清楚"i++"和"++i"及"i--"和"--i"的区别,防止用错。
2.3赋值运算符与赋值表达式
2.3.1赋值运算符和赋值表达式
赋值符号"="就是赋值运算符,作用是将一个数据赋给一个变量或将一个变量的值赋给另一个变量,由赋值运算符组成的表达式称为赋值表达式。
一般形式为:
变量名=表达式
在程序中可以多次给一个变量赋值,每赋一次值,与它相应的存储单元中的数据就被更新一次,内存中当前的数据就是最后一次所赋值的那个数据。
2.3.2复合的赋值运算符
在赋值运算符之前加上其他运算符可以构成复合赋值运算符。
其中与算术运算有关的复合运算符是:
+=,-=,*=,/=,%=。
两个符号之间不可以有空格,复合赋值运算符的优先级与赋值运算符的相同。
表达式n+=1等价于n=n+1,作用是取变量n中的值增1再赋给变量n,其他复合的赋值运算符的运算规则依次类推。
如求表达a+=a-=a*a的值,其中a的初值为12。
步骤:
(1)先进行"a-=a*a"运算,相当于a=a-a*a=12-144=-132。
(2)再进行"a+=-132"运算,相当于a=a+(-132)=-132-132=-264。
2.3.3赋值运算中的类型转换
如果赋值运算符两侧的类型不一致,在赋值前系统将自动先把右侧表达式求得的数值按赋值号左边变量的类型进行转换(也可以用强制类型转换的方式),但这种转换仅限于某些数据之间,通常称为"赋值兼容"。
对于另一些数据,例如,后面将要讨论的地址值,就不能赋给一般的变量,称为"赋值不兼容"。
常用的转换规则如下:
(1)当实型数据赋值给整型变量时,将实型数据的小数部分截断。
如intx;,执行"x=5.21;"后,x的值为5。
(2)当整型数据赋值给实型变量时,数值不变,但以浮点数形式存储到实型变量中。
如floatx=45;
输出x的结果为45.00000。
(3)当double类型数据赋值给float型变量时,取其前面7位的有效数字,存放到float型变量的存储单元中,这时数值可能溢出。
(4)当字符型数据赋值给整型变量时,由于整型变量占两个字节,而字符只占一个字节,只需将字符数据(8位)放到整型变量低8位中,对该整型变量最高位进行符号扩展,其他位补零。
(5)当整型、短整型、长整型数据赋值给一个char类型变量时,将其低8位原封不动地送到char类型变量中(即截断)。
2.4位运算
在计算机中,数据都是以二进制数形式存放的,位运算就是指对存储单元中二进制位的运算。
2.4.1位运算符和位运算
C语言提供6种位运算符,见表2-2。
表2-2位运算符
说明:
(1)位运算中除"~"以外,均为双目运算符,要求两侧各有一个运算量。
(2)运算量只能是整型或字符型数据,不能为实型数据。
2.4.2位运算举例
【例1】下面程序的输出结果是。
#include
main()
{
charx=040;
printf("%d\n",x=x<<1);
}
例题解析:
左移运算是每移一位数值将放大一倍,x为八进制数的40,即十进制数的32,程序是以十进制数方式输出移位后的x,等于64。
实际上,按二进制数展开后也可得到正确结果。
八进制数的40转换成二进制数为00100000,再按题意左移一位后得到01000000,最后按printf语句中的"%d"格式输出其十进制数形式为64。
【例2】设二进制数a是00101101,若通过异或运算a∧b使a的高4位取反,低4位不变,则二进制数b是。
例题解析:
异或运算常用来使特定位翻转,只要使需翻转的位与1进行异或操作就可以了,因为原数中值为1的位与1进行异或运算得0,原数中值为0的位与1进行异或运算结果得1。
而与0进行异或的位将保持原值。
异或运算还可用来交换两个值,不用临时变量。
如inta=3,b=4;,想将a与b的值互换,可用如下语句实现:
a=a∧b;
b=b∧a;
a=a∧b;
所以本题的答案为:
11110000。
【例3】位运算符&|~<<>>∧按优先级从高到低排列的顺序是。
例题解析:
位运算符中求反运算"~"优先级最高,而左移和右移相同,居于第二,接下来的顺序是按位与"&"、按位异或"∧"和按位或"|"。
因此题中的正确顺序为~<<>>&∧|。
第3章基本语句
3.1C语句概述
C语言的语句用来向计算机系统发出指令,一个实际的源程序通常包含若干语句,这些语句用来完成一定的操作任务。
C程序中的语句,按照它们在程序中出现的顺序依次执行,由这样的语句构成的程序结构称为顺序结构。
3.1.1C语句分类
3.1.1.1控制语句
控制语句完成一定的控制功能,C语言共有9种控制语句,见表3-1。
表3-1控制语句
说明:
以上语句中"()"表示一个条件,"…"表示内嵌语句。
3.1.1.2其他类型语句
函数调用语句(由函数调用加一个分号构成),如scanf("%d",&a);。
表达式语句(由一个表达式;构成一个语句),如a=b;。
3.1.1.3空语句
C语言中所有语句都必须由一个分号(;)结束,如果只有一个分号如main(){;},这个分号也是一条语句,称为空语句,程序执行时不产生任何动作,但表示存在着一条语句。
3.1.1.4复合语句
在C语言中花括号"{}"不仅可以用做函数体的开始和结束标志,同时也常用做复合语句的开始和结束标志,复合语句也可称为"语句体"。
在C语言中,任何表达式都可以加上分号构成语句,如"i++;"。
随意加";"会导致很多逻辑上的错误,要慎用,不要乱用。
复合语句中最后一个语句中最后的分号不能忽略不写。
3.2赋值语句
前面已经介绍赋值语句是由赋值表达式和末尾的分号(;)构成的。
这里要提醒读者注意:
"="与"=="是两个不同的运算符,前者才是赋值运算符,而后者是关系运算符,用来进行条件判断,不能把二者混为一谈。
如"i=2;",功能是把数值2放到变量i中,而i==2是判断变量i的值是否为2。
"j=j+1;"在程序执行时,首先取出j中的值,执行加数值1的操作后再把新值放回到j中。
3.3输入输出概念及其实现
(1)数据从计算机内部向外部输出设备(如显示器、打印机等)输送的操作称为"输出",数据从计算机外部向输入设备(如键盘、鼠标、扫描仪等)送入的操作称为"输入"。
(2)C语言本身不提供输入输出语句,可以通过函数来实现输入和输出的操作。
(3)在使用C语言库函数时,首先要用预编译命令"#include"将有关的"头文件"包含到用户源文件中。
这里需要用到编译预处理命令,在后面的章节中我们会详细讲到。
3.4单个字符的输入输出
3.4.1字符输出函数putchar()
putchar()函数的作用是向终端输出一个字符。
如:
putchar(a);
它输出字符变量a的值,a也可以是字符型变量或整型变量。
若a是整型变量,则输出的是ASCII码值为该变量值的那个字符。
3.4.2字符输入函数getchar()
getchar()函数的作用是从终端输入一个字符,getchar()函数没有参数,函数值就是从输入设备得到的字符。
getchar()只能接收一个字符,getchar()函数得到的字符可以赋给一个字符变量或整型变量,也可以不赋给任何变量,作为表达式的一部分。
如果在一个函数中(今为main()函数)要调用getchar()和putchar()函数,在该主函数之前的包含命令"#include"是必不可少的。
、
3.5数据格式的输入与输出
3.5.1printf()函数
printf()函数是C语言提供的标准输出函数,它的作用是向终端(或系统隐含指定的输出设备)按指定格式输出若干个数据。
3.5.1.1printf()函数的一般形式
printf(格式控制,输出表列);
如:
printf("%f,%d",x,y);
printf是函数名,括号内由以下两部分组成:
(1)"格式控制":
用双引号括起来的字符串是"格式控制"字符串,它包括两种信息。
①格式转换说明,由"%"和格式字符组成,如%d、%s等。
上例中,当输出项为int型时,系统规定用d作为格式描述字符,因此,有"%d"。
当输出项为float或double类型时,用f或e作为格式描述字符。
格式描述符要与输出项一一对应且类型匹配。
②需要原样输出的字符(通常指除了格式说明与一些转义字符外的那部分)也写在格式控制内。
(2)"输出表列"是需要输出的一些数据,可以是常量、变量或表达式。
例如:
printf("x=%dy=%d",x,y);
其中,"x=%dy=%d"是格式说明;x,y是输出表列。
输出表列中的各输出项要用逗号隔开。
若x,y的值为7,8,以上两条输出结果为:
x=7y=8
在两数之间有空格,因为在两个格式说明符中间有一个空格。
3.5.1.2格式字符
可以根据需要在"%"与格式字符之间插入"宽度说明"、左对齐符号"-"、前导零符号"0"等。
(1)d格式符,用来对十进制数进行输入输出,其中"%d"按整型数据的实际长度输出,"%md"指定m为输出字段所占的宽度。
(2)o格符,以八进制数形式输出整数,同样可以通过如"%8o"的格式指定输出时所占的宽度。
(3)x符,以十六进制数形式输出整数,样可以通过如"%12x"的格式指定输出时所占的宽度。
(4)u格式符,用来输出unsigned型数据,即输出无符号的十进制数。
(5)c格式符,用来输出一个字符。
(6)s格式符,用来输出一个字符串。
(7)f格式符,用来输出实数(包括单、双精度),以小数形式输出,使整数部分全部如数输出。
(8)e格式符,以指数形式输出实数。
(9)g格式符,用来输出实数。
对于f、e、g格式符可以用"整型数1整型数2"的形式,在指定宽度的同时来指定小数位的位数,其中,"整型数1"用来指定输出数据所占的总宽度,"整型数2"用来确定精度。
精度对于不同的格式符有着不同的含义。
当输出位数多于"整型数2"指定的宽度时,截去右边多余的小数,并对截去的第一位小数做四舍五入处理。
当输出数据的小数位数少于"整型数2"指定的宽度时,在小数的最右边添0,当输出的数据所占的宽度大于"整型数1"指定的宽度时,小数位仍按上述规则处理,整数部分并不丢失。
也可以用"整型数2"的形式来指定小数位数,这时输出的数据所占宽度由系统决定。
通常,系统对float类型提供7位有效位数,对于double类型提供15位有效位数。
3.5.1.3使用printf()函数时的注意事项
(1)在格式控制字符串中,格式说明与输出项从左到右在类型上必须一一对应匹配,如不匹配将导致数据输出出现错误,如在输出long型数据时,一定要用%ld格式控制,而不能用%d格式控制。
(2)在格式控制串中,格式说明与