3.11 疑难解答和上机题
3.11.1 疑难解答
1. 数学算式中的加减乘除和C语言中的加减乘除有什么区别呢?
解答:对于加减和乘运算,两者没有本质的区别,都是进行算术的加减和乘法运算。对于除法,C语言中的规定要严格些,数学算式中不允许0作除数,同样,C语言中也不允许0作除数,并且,当使用0作除数时将使程序运行崩溃。另外,C语言中,对于算术运算,总是向高精度的参与运算的数据靠拢,当两种运算操作数类型相同时,结果也是这种类型。
2. b=b+1和b++有什么差别呢?
解答:两者并无本质区别,只不过表达形式不同而已。
3. %和/有什么不同?
解答:前者是求两个整数相除的余数,也称为模除,但除数不能为0,并且参与运算的必须为整数。后者是算术运算除法符号,用于两个数据相除,得商,同样除数也不能为0,但可以是两个浮点数相除。在数学算式中不存在%这个符号。
4. 10/3和10./3在运算时有什么差别?
解答:C语言中进行算术运算时会进行精度转换,计算过程和结果以高精度数据为准。10/3为两个整型数相除,结果仍为整型,因此结果为3。10./3中,10.为浮点数,则运算时首先将3转换为浮点数,然后进行除运算,结果仍为浮点数3.333333。
5. 将浮点数强制类型转换为整型数据,是否会影响其精度呢?
解答:会的,强制类型转换仅仅是取浮点数的整数部分,小数部分将被舍弃,因此计算时将造成精度降低。程序设计时应注意,在支持浮点运算的系统中,尽量使用浮点运算,以提高精度。
6. C语言中表达式5<b<3与数学中的意义一样吗?
解答:不一样。C语言中,关系运算符<为左结合性。因此,关系表达式5<b<3等价于(5<b)<3,假设b=10,则表达式5<b为真,值为1,所以,原表达式等效于1<3,因此表达式为真,值为1。而在数学计算中,假若b=10,那么5<10<3的表达式显然是矛盾的,但在C语言中,则不存在矛盾的情况。
7. 逻辑运算符和关系运算符结合在一起的表达式如何执行?例如:表达式!(a+b>c==5)是真还是假?
解答:当有多种运算符在一个表达式中参与运算时,一定要弄清楚各运算符的优先级和结合性,这两个因素对程序的执行会产生至关重要的影响。上述表达式中,算术运算符+、关系运算符>与= =的优先级顺序为:
+高于>高于==
因此,括号内表达式a+b>c==5等价于((a+b)>c)= =5。已知a=1,b=2,c=3,因此,表达式(a+b)>c为假,值为0,则原表达式等效于!(0==5),由于表达式0==5为假,值为0,因此!0为真,值为1,因此,原表达式为真,值为1。
8. &和&&的区别主要体现在哪里?
解答:首先,&是位与运算符,而&&是逻辑与运算符,它们一个是位运算符,一个是逻辑运算符,两者类别不同。此外,&运算符构成的表达式可以是任何值,而&&构成的表达式只有两个值:0(假),1(真)。前者主要用于对某变量进行位操作,而后者主要是进行判断和分析。
9. 条件运算符中冒号两边的表达式有前后运算顺序吗?例如:
定义x=3,y=5,执行(x>y)? x++: --y后,x和y的值变为多少?
解答:条件表达式中,根据判断条件不同,执行过程也有所差别。例题中,由于x=3,y=5,则表达式x>y为假,因此条件表达式(x>y)? x++: --y的值为--y,即为4,但程序并未执行x++表达式,因此x的值仍为3,y的值变为4。
10. 请详细描述a+=15的执行过程。
解答:a+=15的执行顺序为:第1步取内存中a的值10,将其放入运算器;第2步与常量15进行加和运算,产生和25;第3步将25赋值给变量a;第4步将a所在的内存空间改写为25。这是表达式a+=15的逻辑运算顺序。如图3-1所示为表达式的执行示意图。
图3-1 表达式执行示意图
下面讨论更为复杂的复合赋值运算,先看下面的程序:
01 #include<stdio.h> 02 main() 03 { 04 int m=5; 05 printf("m=%d, m+=m-=m*m=%d, m=%d", m, m+=m-=m*m, m); 06 }
程序运行输出结果为:
m = -40, m+=m-=m*m = -40, m = 5
C语言中,有一块叫做堆栈的区域,专门作为函数调用以及循环嵌套时的存储区域。堆栈区域主要存储中断时变量的值,以便中断结束后重新将这些值输出给程序使用,避免中断时这些变量的值被修改。函数调用时参数从右至左被压入堆栈,所以,程序中的printf函数,首先入栈的是输出参数表列中最后一个表达式m,入栈的值是5,其次入栈的是表达式m+=m-=m*m的值。
表达式m+=m-=m*m的计算过程为: m = m + (m=m-(m*m))
表达式运算期间m会进行两次赋值,一次是m = m-(m*m),结果为-20,另外一次是m =m+(-20),此时的m已被赋值为-20,因此赋值过程为m = -20 + (-20),结果为-40,赋值后m的值变为-40,同时也是整个表达式的值。
表达式m+=m-=m*m的值被压入栈内的同时,m的值也被修改为-40,因此最后一个入栈的参数即最左边的m变为-40。
printf执行输出时,输出顺序是从左到右,因此输出时先输出最后入栈的参数m=-40,因此输出值-40,其次输出表达式m+=m-=m*m的值-40,最后输出最初入栈的值5。
因此输出结果为:
m = -40, m+=m-=m*m = -40, m = 5
3.11.2 上机题
1. C语言规定,逗号表达式的值为最后一个表达式的值,试编写程序,验证a = 12, b =100, c = a+b的值。
2. 整数和浮点数在同一表达式中做四则算术运算时,系统隐含将整数类型转换为浮点类型计算。试编写程序,分别使用%d和%f格式输出1.0/2的值,并分析结果差别。
3. 已知圆面积计算公式为:S=pi * r2,其中pi表示圆周率。试编写程序,计算半径为r=5的圆面积,并输出到屏幕上,取pi=3.14,精确到小数点后6位。(提示:C语言中,乘方可以使用乘积的形式实现)
4. C语言中,a++称为++运算符的右运算,表达式的值为a,++a称为++运算符的左运算,表达式的值为a+1,试编写程序验证执行b=++a+a++后,a和b的值。
5. 试编写程序,使用scanf函数输入b的值,并判断b是否属于区间-5<b<10,若是,输出1,否则输出0。(提示:注意C语言中对不等式-5<b<10的表达方法)
6. 试编写一段完整的程序,使用scanf函数输入a的值,判断a是否等于0,若等于,输出1,否则输出0。(提示:可使用关系运算符==)
7. 已知a=0,试编写程序,输出表达式!(a>10)的值。
8. C语言中,通常使用关系表达式和逻辑表达式结合判断变量是否属于某区间内。试编写程序,使用printf函数输入年数year,并判断是否属于[2000,2020]的区间,若是,则输出1,否则输出0。
9. C语言中,倍乘运算可以使用左移运算符实现,试编写程序,定义int型变量a并赋初值,使用位运算实现变量a的倍乘。(提示:使用左移运算符<<实现,读者可试验输入负数或正数对a的影响)
10. 两个整型数据作除法运算时,仍然得到整型值的结果,而使用强制类型转换,将被除数转换为浮点类型则可以得到正确的结果。试编写程序输出a! /b!的值,已知a=5, b=3。输出结果精确到小数点后6位。