《C语⾔程序设计》第三章基本算术运算⽬录:
3.1  C运算符和表达式
3.1.1  算术运算符和表达式
3.1.2  复合的赋值运算符
3.1.3  增1和减1运算符
3.2  宏常量与宏替换
3.3  const常量
3.4  ⾃动类型转换与强制类型转换运算符
3.5  常⽤的标准数学函数
3.6  本章知识点⼩结
3.7  本章常见错误⼩结
3.1.1  算术运算符和表达式
算术运算符的优先级与结合性
运算符含义
需要的操作
数个数运算实例
运算
结果
优先级结合性
-
取相反数
(Opposite Number)1个(⼀元)
-
1
-(-1)
-1
1
最⾼从右向左
* / %乘法(Multiplication)
除法(Division)
求余(Modulus)
2个(⼆元)
12/5
12.0/5
11%5
11.0%(-5)
(-11)%5
2
2.4
1
1
-1
较低从左向右
+ -
加法(Addition)
减法(Subtraction)
2个(⼆元)
5+1
5-1
6
4
最低从左向右
算术表达式:由算术运算符及其操作数组成的表达式;也称为运算对象,它可以是常量、变量、函数。
只需⼀个操作数的运算符称为⼀元运算符(或单⽬运算符),需要两个操作数的运算符称为⼆元运算符(或双⽬运算符),需要三个操作数的运算符称为三元运算符(或三⽬运算符)。条件运算符是C语⾔提供的唯⼀⼀个三元运算符。
不同于数学中的算术运算,C语⾔中的算术运算的结果与参与运算的操作数类型相关。以除法运算为例,
两个整数相除后的商仍为整数。例如,1/2与1.0/2运算的结果值是不同的,前者是整数除法,后者则是浮点数除法。eg.12/5=2, 12.0/5.0(或者12/5.0,或者12.0/5)=2.4。
在C语⾔中,求余运算限定参与运算的两个操作数必须为整型,不能对两个实型数据进⾏求余运算。
注意,C语⾔中没有幂运算符。
//计算并输出⼀个三位整数的个位、⼗位和百位数字之和。
#include<stdio.h>
int main(void)
{
int x=153,b0,b1,b2,b3,sum;
b2=x/100;            //百位
b1=(x-b2*100)/10;    //⼗位
b0=x%10;            //个位
sum=b0+b1+b2;
printf("b2=%d,b1=%d,b0=%d,sum=%d",b2,b1,b0,sum);
return0;
}
输出:
b2=1,b1=5,b0=3,sum=9
3.1.2  复合的赋值运算符
涉及算术运算的复合赋值运算符有5个:+=,-=,*=,/=,%=
例如:n*=m+1等价于n=n*(m+1),但不等价于n=n*m+1.
#include<stdio.h>
int main(void)
{
int a=3;
a+=a-=a*a;
printf("a=%d",a);
return0;
}
输出:a=-12
#include<stdio.h>
int main(void)
{
int a=3;
a+=a-=a*=a;
printf("a=%d",a);
return0;
}
输出:a=0
增1和减1运算的例⼦(初始n=3)
语句等价的语句执⾏该语句后m的值执⾏该语句后n的值
m=n++;m=n;
n=n+1;
34
m=n--;m=n;
n=n-1;
32
m=++n;n=n+1;
m=n;
44
m=--n;n=n-1;
m=n;
22
3.1.3  增1和减1运算符
语句        m=-n++;
等价于      m=-(n++);
进⼀步,等价于    m=-n;    n=n+1;
假使 int n=3,则m=-3,n=4.
后缀形式与前缀形式的区别在于:后缀是先使⽤变量的值,然后再增1(减1);前缀是先增1(减1),然后再使⽤变量的值,并且后缀增1(减1)运算符的优先级⾼于前缀增1(减1)运算符,前者是左结合的,⽽后者是右结合的。
3.2  宏常量与宏替换
//计算并输出半径r=5.3的圆的周长和⾯积。
#include<stdio.h>
int main(void)
{
double r=5.3;
printf("circumference=%f\n",2*3.14159*r);
printf("area=%f\n",3.14159*r*r);
return0;
}
输出:
circumference=33.300854
area=88.247263
若要做到⼀次编译,多次运⾏计算不同半径的圆的周长和⾯积,则每次运⾏时可以让⽤户从键盘输⼊圆的半径r的值,这就要⽤到C标准函数库中的函数scanf()。
//从键盘输⼊圆的半径r,计算并输出圆的周长和⾯积。
#include<stdio.h>
int main(void)
{
double r;
printf("Input r:");  //提⽰⽤户输⼊半径的值
scanf("%lf",&r);      //以双精度实型从键盘输⼊半径的值
printf("circumference=%f\n",2*3.14159*r);
printf("area=%f\n",3.14159*r*r);
return0;
}
程序会在屏幕上显⽰:
Input r:
假使输⼊5.3并回车,则输出
Input r:5.3
circumference=33.300854
area=88.247263
scanf()函数⽤于从键盘输⼊⼀个数,%lf指定输⼊的数据类型应为双精度实型。第六⾏语句中r前⾯的&是必要的,&称为取地址运算符,&r指定了⽤户输⼊数据存放的变量的地址。
幻数:在程序中直接使⽤的常数,如π,但幻数存在影响程序的可读性和可维护性的问题,常把幻数定义为宏常量或const常量。
#include<stdio.h>
#define PI 3.14159    //定义宏常量PI
int main(void)
{
double r;
printf("Input r:");
scanf("%lf",&r);
printf("circumference=%f\n",2*PI*r);  /*编译时PI被替换成3.14159*/
printf("area=%f\n",PI*r*r);
return0;
}
宏常量:也称符号常量,是指⽤⼀个标识符号来表⽰的常量,这时该标识符号与此常量等价。宏常量是由宏定义编译预处理命令来定义的。
宏定义的⼀般形式为:#define 标识符字符串,其作⽤是⽤#define编译预处理指令定义⼀个标识符和⼀个字符串,凡在源程序中发现该标识符时,都由其后指定的字符串来替换。
宏名:宏定义中的标识符,习惯⽤字母全部⼤写的单词来命名;宏替换:将程序中出现的宏名替换成字符串的过程。
注意:宏定义中的宏名与字符串之间可有多个空⽩符,但⽆需加等号,且字符串后⼀般不以分号结尾,因为宏定义不是C语句,⽽是⼀种编译预处理命令。
3.3  const常量
宏常量的缺陷:宏常量没有数据类型,字符串替换时极易产⽣错误。
:可以声明具有某种数据类型的常量。在声明语句中,形式为:const 类型常量名 = 初始值;    例如:const  double PI = 3.14159;
//使⽤const常量定义π,编程从键盘输⼊圆的半径r,计算并输出圆的周长和⾯积。
#include<stdio.h>
int main(void)
{
const double PI=3.14159;  //定义实型的const常量PI
double r;
printf("Input r:");
scanf("%lf",&r);
printf("circumference=%f\n",2*PI*r);
printf("area=%f\n",PI*r*r);
return0;
}
3.4  ⾃动类型转换与强制类型转换运算符
1. 表达式中的⾃动类型转换
类型提升:C编译器在对操作数进⾏运算之前将所有操作数都转换成取值范围较⼤的操作数类型,可以避免数据信息丢失情况的发⽣。
整数提升:类型提升的规则如下图所⽰,纵向箭头表⽰必然的转换,即将所有的char和short都提升为int的步骤称为整数提升。
float                                                                          char,short
↓↓
long double  ←  double  ←  unsigned long  ←  long  ←  unsigned int  ←  int
⾼←—————————————————————————————— 低
上图横向箭头表⽰不同类型的操作数进⾏混合运算时由⾼到低的类型转换⽅向,但不代表转换的中间过程。
例如,⼀个int型操作数与⼀个 float型操作数进⾏算术运算,则在对其进⾏运算之前要先将 float型操作数⾃动转换为 double型,并将int型操作数转换成 double型(注意,⽆须经过int型先转换为 unsigned int再转换成long型,再转换为 unsignedlong型,再转换为 double型的过程)。⼀个特例是:如果⼀个操作数是l
ong型,另⼀个是unsigned型,同时unsigned型操作数的值⼜不能⽤long型表⽰,则两个操作数都转换成 unsigned long型。
2.赋值中的⾃动类型转换
在⼀个赋值语句中,若赋值运算符左侧(⽬标侧)变量的类型和右侧表达式的类型不⼀致,则赋值时将发⽣⾃动类型转换⾃动类型转换。类型转换的规则是:将右侧表达式的值转换成左侧变量的类型。
⾃动类型转换虽然给取整等某些特殊运算带来⽅便,但在某些情况下有可能会发⽣数据信息丢失、等问题。
3.强制类型转换运算符
强制类型转换运算符简称强转运算符或转型运算符,它的主要作⽤是将⼀个表达式值的类型强制转换为⽤户指定的类型,它是⼀个⼀元运算符,与其他⼀元运算符具有相同的优先级。通过下⾯⽅式可以把表达式的值转为任意类型:(类型)表达式
强转与指针,可并称为C语⾔的两⼤神器,必须恰当使⽤。
//演⽰强制类型转换运算符的使⽤。
#include<stdio.h>
int main(void)
{
int m =5;
printf("m/2=%d\n",m/2);
printf("(float)(m/2)=%f\n",(float)(m/2));
printf("(float)m/2=%f\n",(float)m/2);
printf("m=%d\n",m);
return0;
}
输出:
复合赋值运算符的含义
m/2=2
(float)(m/2)=2.000000
(float)m/2=2.500000
m=5
分析:
表达式m/2是整数除法,其运算结果仍为整数,因此输出的第⼀⾏结果值是2;
表达式(float)(m/2)是将表达式(m/2)整数相除的结果值(已经舍去了⼩数位)强转为实型数(在⼩数位添加了0),因此输出的第⼆⾏结果值是2.000000,可见这种⽅法并不能真正获得m与2相除后的⼩数部分的值;表达式(float)m/2是先⽤(float)m将m的值强转为实型数据,然后再将这个实型数据与2进⾏浮点数除法运算,因此输出的第三⾏结果值是2.500000;
由于(float)m只是将m的值强转为实型数据,但是它并不改变变量m的数据类型,因此输出的最后⼀⾏结果值仍然是5.
3.5  常⽤的标准数学函数
/*已知三⾓形的三边长为a、b、c,计算三⾓形⾯积的公式为:,其中s=(a+b+c) /2
试编程从键盘输⼊a、b、c的值(假设a、b、c的值可以保证其构成⼀个三⾓形),计算并输出三⾓形的⾯积*/
#include<stdio.h>
#include<math.h>
int main(void)
{
float a,b,c,s,area;
printf("Input a,b,c:");
scanf("%f,%f,%f",&a,&b,&c);
s=(a+b+c)/2;
area=(float)sqrt(s*(s-a)*(s-b)*(s-c));
printf("area=%f\n",area);
return0;
}
输出:
Input a,b,c:3,4,5↙
area=6.000000
分析:当a、b、c被定义为整型变量时,将数学公式s=(a+b+c)/2写成如下各种形式的C语⾔表达式: s=0.5*(a+b+c)    s=1.0/2*(a+b+c)    s=(a+b+c)/2.0    s=(float) (a+b+c)/2  都是正确的。⽽如果写成s=1/2*(a+b+c) 或者 s=(float)((a+b+c)/2) 虽⽆语法错误,但计算结果错误。
注意,如果将第5⾏的变量改为double类型,那么第9⾏的sqrt()的返回值⽆需强转为float,这样计算的结果会⽐float计算的结果精度更⾼,导致输出结果中的⼩数后的某些位有可能不⼀样。
使⽤时,只要在程序开头加上如下的编译预处理命令即可:
#include<math.h>
3.6  本章知识点⼩结
3.7  本章常见错误⼩结
常见错误实例常见错误描述错误类型
2*π*r表达式中使⽤了⾮法的标识符编译错误
4ac 或者 4×a×c将乘法运算符*省略,或者写成×编译错误
使⽤⽅括号“[”和“]”以及花括号“{”和“}”限定表
1.0/
2.0+[a-b]/{a-b}
编译错误
达式运算顺序
使⽤数学函数运算时,未将参数⽤圆括号括起来,且
sinx
编译错误
未注意到其定义域要求和参数的单位
3.5%0.5对浮点数执⾏求余运算编译错误
1/2误将浮点数除法当做整数除法运⾏时错误
float(m)/2强转表达式中的类型名未⽤圆括号括起来运⾏时错误
误以为(float)m这种强制运算可以改变变量m的
理解错误
类型和数值
误以为⽤双括号括起来的字符串中与宏名相同的字
理解错误
符也被宏替换,误以为宏替换时可以做语法检查
—误以为三⾓函数中的⾓的单位是⾓度理解错误
将宏定义当做C语句来使⽤,在⾏末加上了分号,或
#define PI = 3.14159;
编译错误
者在宏名后加上了“=”
将复合的赋值运算符+=,-=,*=,/=,%=的两个字符
+=,-=,*=,/=,%=
编译错误
中间加⼊了空格
(a+b)++对⼀个算术运算符使⽤增1或者减1运算编译错误

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。