原标题:C语言运算符
一、前言
在嵌入式开发中,我们一般选用C语言作为开发语言。一个主要的原因在于C语言提供了大量的运算符,比如我们对硬件的操作一般涉及到对位的操作,而C语言就提供了这样的运算符,这是其他语言不具备的。
二、C语言运算符有哪些
C语言有大量的运算符,可大致分为以下几类:括号与结构体符号、单目、算术、移位、关系、位、逻辑、三目、赋值、逗号。
括号与结构体符号:括号包括()、[],结构体符号指的是结构体成员引用时的符号“->”、“.”,他们也是运算符,并且优先级与括号相当,这也是我们把两者放在一起讨论的原因。至于如何使用则是结构体的内容。
单目运算符:单目运算符有很多,例如:!逻辑非、~按位取反、++自增、--自减、+正、-负、&求地址运算符、*间址运算符、sizeof()求所占字节数、(类型名)强制类型转换。这些运算符的运算对象只有一个。其中&与*属于指针内容,我们不做细说。逻辑非我们在下面逻辑运算符时说明,按位取反我们在下面位运算符时说明,强制类型转换我们在格式转换时说明。Sizeof()首先不是函数,用于求类型的所占字节数。例如:int a;sizeof(a)或sizeof(int)得到的值都是4,即整型占4个字节。()中可以是变量也可以是数据类型也可以是字符串常量。例如:char ch[20]=”hello”;我们定义字符数组来保存字符串,当我们要求字符串长度时我们发现sizeof(ch)得到的大小为20,即数组的大小,那么怎么求字符串长度呢?我们可以用字符串的相关函数strlen(),但是也可以sizeof(“hello”);它的结果为6,即计算字符串最后的空字符’0’。++与--是我们经常用到的运算符,简单来说,有以下四种情况:
a=10,a++ ++在a的后面,先把a的值赋值给表达式,a在自加1。即 a=10,b=a,a=a+1
a=10,++a ++在a的前面,a先自加1,再把a的值赋值给表达式。即 a=10,a=a+1,b=a
a=10,a-- --在a的后面,先把a的值赋值给表达式,a在自减1。即 a=10,b=a,a=a-1
a=10,--a --在a的前面,a先自减1,再把a的值赋值给表达式。即 a=10,a=a-1,b=a
上例中a++/++a/a--/--a代表表达式,我们可以理解为:b=a++/b=++a/b=a--/b=--a
算术运算符:+、-、*、/、%。需要注意的是,在做相乘运算时,*不能省略。/表示除号,%表示取余。例:10/3=3 10%3=1 这里%是取10除以3后的余数,所以结果为1。要注意的是%左右两边必须都是整数。而10/3的结果为什么是3而不是3.3333呢?这里涉及到格式转换的知识,是我们格式转换部分要说的。
移位运算符:>> << 。移位运算符右移与左移是对位进行操作。例如:a=10,b=a>>1,
此例的意思是把数值a往右移动1位,把结果赋值给b。我们知道数据在内存中以二进制存放,10对应的二进制位1010,各位往右移一位得到0101,最右边的0被移出去,左边空的一位我们补0,所以b的值为0101,即5。这是右移,如果数据右边有足够多的0,我们可以往右移动多位,规律为往右移动移位相当于除以2,移动两位相当于除以2^2,移动n位相当于除以2^n.左移<
相当于把1010往左移两位变为10 1000,即b的值为40.我们发现在数值上相当于a*2^2。
所以我们的规律就是:往右移n位,相当于除以2^n 。往左移n位,相当于乘以2^n 。实际上我们就是用左移右移来代替乘除的,这样不需要计算与赋值过程,只需要将各位移动,更加快捷。
关系运算符:>大于、= 大于或等于、<=小于或等于、==等于、!=不等于。关系运算符用于比较大小,需要注意的是:1、关系运算符的写法。当要表示1010&&a<20。
&&是逻辑与运算符,表示并且。2、关系运算符的值是逻辑值。例如:a=10,b=20; a
如果关系成立,即逻辑为真,那么值就是1.如果关系不成立,即逻辑为假,那么值就是0.
逻辑运算符:&&逻辑与、||逻辑或、!逻辑非。逻辑运算符的值也是逻辑值,需要注意的是对数据来说非0为真,0为假。这三个运算符的关系为:
逻辑与:两个数据全为真的时候结果才为真
1 1 1
1 0 0
0 1 0
0 0 0
逻辑或:两个数据有一个为真结果就为真
1 1 1
1 0 1
0 1 1
0 0 0
逻辑非:!是单目运算符,非真为假,非假为真。!0结果是1,!-1结果是0,!1结果也是0
位运算符:按位与&、按位或、按位取反、按位异或^。这些运算符也是对位的操作与逻辑运算符要注意区分。例如:10&20。我们看做:让各位进行相与
01010
& 1 0100
00000
那么10&20的结果就是0。
与或关系我们都知道,在补充一下异或关系,相同为假,不同为真。
1 1 0
1 0 1
0 1 1
0 0 0
我们知道这些都是对位的操作,我们要额外说一下按位取反。例如:int a=1;~a的值为什么呢?我们打印之后发现结果为-2。这涉及到数据存放的知识。我们要知道数据以补码形式存放、补码形式打印。a的二进制,0000 0001,是一个正数,它的补码为它本身0000 0001,这里我们只以一个字节为例。当我们~a后按各位取反,得到1111 1110,当我们打印这个数据时,需要补码打印,这时候它的最高位为1,表示负数,负数的补码为它的反码加一。即:
1000 0001+1 = 1000 0010 对应的十进制为-2。
三目运算符:?:。它是条件语句的内容,C语言中只有这一个三目运算符,即运算对象有三个。例如:a=10,b=20,a>b?a:b的值为b的值。即a大于b为真时a的值是表达式的值,否则b的值是表达式的值。
赋值运算符:=、+=、-=、*=、/=、%=、&=、^=、!=、<<=、>>=。即上面的符号与=相结合。=叫赋值号,使用时要注意,例如:int a=10,表示把数据10赋值给整型变量a。a+=b表示a=a+b,其他符号用法相同。
逗号运算符:“,”。例如:a=(b+c,c+d,d+e);a的值为d+e的值,即最后一个表达式的值。所以逗号表达式的值为最后一个式子的值。但这并不表示前面的式子没用,例如:a=(b++,c+d,b+d);我们要从左向右计算,因为b++改变了b的值,所以要先b++,在b+d。
三、运算符优先级
我们在做简单的符合运算时,比如:a+b/c+d 我们是先让b/c,在让三者进行相加。这里/号比加减运算优先级要高。同理,当我们的式子包含了以上运算符时,我们就要理清先算谁再算谁。这里我们已经将运算符的优先级整理为一句话:优先级从高到低依次为:
() 单目算术 移位 关系 位 逻辑 三目 赋值 逗号
四、运算符结合性
这里讨论的情况是当式子中几个运算符优先级相同时,应该先算谁再算谁。例如:*p++,我们知道*与++都是单目运算符,这时候先算哪个呢?我们也给大家总结了一句话:
单目、三目、赋值运算符结合性自右向左,其他运算符结合性自左向右。
我们给了如下三个例子:
Int a=10,int *p=&a,求*p++。根据结合性自右向左,应该先算p++,即p指向a上面的那块空间。所以*p++表示a上面那块空间的值。
a>b?a>c?a:c:b>c?b:c; 这个式子表示的是求三个数最大值。根据结合性自右向左,先算b>c?b:c求b和c的最大值,在算a>c?a:c求a和c的最大值。最后比较a与b的值。
a=b+c=a+b;这种写法是错误的,因为他的结合性自右向左,且+优先级比=高,所以是先把a+b的值赋值给b+c,我们无法把一个值赋值给表达式,即赋值号左边不能为式子。
五、格式转换规则
1、运算符左右两边类型相同时,得到的结果也是这个类型。例:1/2=0,10/3=3
2、运算符左右两边类型不同时,先把他们往精确度更高的一侧转换,变为相同的类型。 例:1.0/2=0.5,10/3.0=3.333333
3、赋值号右面的数据会自动转换为左面的数据类型。例:int a=2.678。a的值为2
4、我们可以对数据进行强制类型转换。例:float a=2.789,(int)(a);a的类型变为int,值为2
责任编辑: