(1)自动转换(5+5.000000=?结果是10还是10.000000):发生在不同类型的数据混合运算时,由编译系统自动完成。
不同的数据类型,要转换成精度较高的。
A、转换按数据长度增加的方向进行,确保精度不降低,比如:int型和long型运算时,先把int量转成long型后再进行运算
B、Char和short类型要转换成int 型,然后再参加运算。
C、在赋值运算中,赋值号两边的数据类型不同时,赋值号右边的类型将转换为左边的类型,如果右边的数据类型长度比左边长,将丢失一部分,丢失的部分按四舍五入向前舍入。
比如:计算10+‘a’+5*5.000000 (10和5为整型,5.000000 为双精度实型)
先计算‘a’的整型为97,+10=107;//将char转换为int 型
计算5*5.000000=25.000000;//将整型5转换为double型实型
计算107+25.000000=132.000000; //将整型107转换为double型;
所以它的最终结果为精度最高的double型。
比如:我们来看两个程序实例
//#include <stdio.h> #include <iostream> using namespace std; void main() { unsigned int a=6; //定义无符号整型 int b=-20; //定义有符号整型 cout<<a+b<<endl;//输出a+b的值,类型随a+b值的类型而定 } |
为什么是一串很大的整数呢?而不是-14呢?问题就在自动转换上,我们观察上述讲过的转换规则,unsigned和int同时出现运算时,int需要转换成unsigned,即:有符号需要转换成无符号类型。程序中的-20需要转换成无符号整型。
//#include <stdio.h> #include <iostream> using namespace std; void main() { unsigned char a=6; //定义无符号整型 char b=-20; //定义有符号整型 cout<<a+b<<endl;//输出a+b的值,类型随a+b值的类型而定 } |
将int型修改为char类型之后,结果竟然是-14,这又是为什么呢?还是自动转换规则。看规则,int以下类型(short,char不管有无unsigned)计算会转为int,也就是说不管有没有符号,char类型都要转换成int型,所以a+b遵循了有符号整型的运算。
(2)强制类型转换
区别与自动转换,强制转换很明显是强制的。格式为:(类型说明符)表达式
比如:int a ; (float) a 的意思是将整型a 强制转换为了实型。(int)(x+y)的意思是将x+y的值转换为整型。
(3)需要注意的是:无论是自动转换或者是强制转换,都只是为本次运算的需要而对变量的数据长度进行的临时性转换,而不改变数据说明时对该变量定义的类型。
如下程序:
#include <stdio.h> main() { float f=5.75; printf("(int)f=%d\nf=%f\n",(int)f,f); } |
1.运算符的优先级与结合性
|
2.算术运算(+、-、*、/、%)
(1)乘除取余的优先级要高于加减;
(2)“/”除运算,参加除运算的变量均为整数,结果也为整数(舍去小数),多数机器上采取“向零取整”的原则。比如:7/4=1(而不是1.75),-7/4=-1。
(3)“%”,参与模运算的变量必须都为整型,其结果为两数相除的余数,并且余数与被除数的符号相同。比如:7%4=3, -8%5=-3, 8%-5=3 。
3.赋值运算
(1)变量名=表达式,运算顺序是从右向左。比如:x=y=z=0, x=(y=(z=0))
(2)当赋值运算符两边的数据类型不同时,系统将自动进行类型转换,赋值运算符右边的数据类型转换成左边的变量类型,在上一篇中已经说过了。
(3)复合赋值运算:比如:n+=1等价于n=n+1; x*=y+1等价于x=x*(y+1)
4.自增自减运算
如果n=3 ,则n的值和m的值如下表所示
|
关于自增自减是一个重要的概念,在之后的指针学习中还会重点学习。
5.逗号运算
(1)表达式1,表达式2,....表达式n。自左向右结合。
(2)表达式n的值为整个逗号表达式的值。比如:a=(1,2,3,4,5,6),则a的值等于6。也就是最后一个的值。
(3)逗号运算符在所有运算符中的优先级别最低,它往往起到了把若干个表达式串联起来的作用。比如:a=3*4,a*5,a+10。 从左向右 先去3*4,然后将12的值赋给a,然后计算a*5。将60的值赋给a,然后计算a+10的值。
6.关系运算与逻辑运算
关系运算无非就是大于(>)小于(<),逻辑运算有非(!)与(&&)或(||)
逻辑表达式的值只有真(1)和假(0)两个值。
A的取值 | B的取值 | !A(求反) | A&&B | A||B |
非0 | 非0 | 0 | 1 | 1 |
非0 | 0 | 0 | 0 | 1 |
0 | 非 | 1 | 0 | 1 |
0 | 0 | 1 | 0 | 0 |
对于关系运算来说,a>b>c并不代表着a的值比b大,b的值比a大。关系运算与逻辑运算需要密切合作。我们来举一个例子:看两个程序。
#include <stdio.h> main() { int a=6,b=4,c=1; if(a>b>c) { printf("OK\n"); } else{ printf("ERROR\n"); } } |
我们看到的结果竟然是ERROR,而不是我们预想的OK,这是为什么呢?原因就在判断上。在数学上,a>b>c一点都没有错,但是在我们的C程序中,计算机判断条件的依据只有两种结果,那就是1(真)或者是0(假)。比如:a>b是真,所以a>b的值为1,然后1>c吗?很显然1=c,所以if()条件中的条件并不成立,所以结果为ERROR。那这样怎么改呢?很简单,用逻辑运算符
#include <stdio.h> main() { int a=6,b=4,c=1; //if(a>b>c) if(a>b && b>c) { printf("OK\n"); } else{ printf("ERROR\n"); } } |
7.1:位运算之取反(~)
(1)取反能对一个二进制的每一位都取反。
看一个程序实例:
#include <stdio.h> main() { unsigned char a,b;//定义无符号 //char a,b; a=26; b=~a;//对a取反 printf("b=%u\n",b);//以无符号输出 } |
分析一下:char类型默认分配一个字节,即8位。26的二进制为:00011010
对26的二进制取反(~a)得:11100101,我们在深入剖析类型修饰符unsigned中讲解过,无符号的二进制最高位为数据位,所以11100101的十进制为229。
(2)为了便于区分有符号和无符号的区别,我们再来做一个程序实例:
#include <stdio.h> main() { //unsigned char a,b;//定义无符号 char a,b;//定义有符号 a=26; b=~a;//对a取反 //printf("b=%u\n",b);//以无符号输出 printf("b=%d\n",b);//以有符号输出 } |
26的二进制:00011010,取反:11100101,char类型默认有符号(我的是有符号,有些课本中说无符号),所以最高位为符号位,所以是负数,对11100101减一取反是:10011011,转换成二进制为-27。
对于这一块不理解的同学可以参考:C语言进阶[暑期特别篇]深入剖析类型修饰符unsigned
7.2:位运算之左移(<<)
左移是将一个数的各个二进制位全部向左平移若干位,左边移出的部分忽略,右边空出的位置补0,比如:
A = 0 0 0 1 1 0 1 0
A<<2=0 1 1 0 1 0 0 0
一个数据,每左移一位相当于乘以2,左移2位相当于乘以4。比如:4左移2位=4*4=16。
7.3 位运算之右移(>>)
右移是将一个数的各个二进制位全部向右平移若干位,右边移出的部分忽略,左边空出的位置对于无符号数补0,对于有符号数,若原符号位为0,则全补0,若原符号位为1,则全补1。比如:
A 被定义为unsigned(无符号) char
A= 1 0 0 1 1 0 1 0
A>>2 = 0 0 1 0 0 1 1 0
A被定义为char (默认有符号)
A= 1 0 0 1 1 0 1 0
A>>2 = 1 1 1 0 0 1 1 0
7.4 位运算之与或(&&、|)
比如: a= 1 0 1 1 1 0 1 0
b= 0 1 1 0 1 1 1 0
a&&b= 0 0 1 0 1 0 1 0 只有1和1是1,其它的全是0
a|b= 1 1 1 1 1 1 1 0 只要有一个1,就是1啦
7.5 位运算之异或(^)
异或运算的作用是判断两个相应位的值是否相异。相异为1,反之则为0。
a= 1 0 1 1 1 0 1 0
b= 0 1 1 0 1 1 1 0
a^b= 1 1 0 1 0 1 0 0