运算符是告诉编译程序执行特定算术或逻辑操作的符号。C语言的运算符和表达式相当丰富,这在高级语言中是很少见的。C语言常用的运算符见表3-3。
表3-3 C语言常用的运算符
C语言规定了一些运算符的优先级和结合性。优先级是指当运算对象两侧都有运算符时,执行运算的先后次序;结合性是指当一个运算两侧的运算符的优先级别相同时的运算顺序。C语言运算符的优先级及结合性见表3-4。
表3-4 C语言运算符的优先级及结合性
续表
1.算术运算符
算术运算符可用于各类数值运算,包括加(+)、减(-)、乘(*)、除(/)、求余(又称为取模运算,%)、自增(++)和自减(--)共7种运算。
用算术运算符和括号将运算对象连接起来的式子称为算术表达式,其运算对象包括常量、变量、函数和结构等。例如:
算术运算符的优先级规定为:先乘除求余,后加减,括号最优先。也就是说,在算术运算符中,乘、除、求余运算符的优先级相同,并高于加减运算符。在表达式中若出现括号,括号中的内容的优先级最高。例如:
算术运算符的结合性规定为自左至右方向,又称为“左结合性”,即当一个运算对象两侧的算术运算符优先级别相同时,运算对象与左面的运算符结合。例如:
自增(++)和自减(--)运算符的作用是使变量的值增加或减少1。例如:
2.赋值运算符和赋值表达式
【一般赋值运算符】 在C语言中,最常见的赋值运算符为“=”,其作用是计算表达式的值,再将计算结果赋值给左边的变量。赋值运算符具有右结合性,即当一个运算对象两侧的运算符优先级别相同时,运算对象与右面的运算符结合。
其一般格式为
例如:
如果赋值运算符两边的数据类型不相同,系统将自动进行类型转换,即把赋值号右边的类型转换成左边的类型。具体规定如下:①将实数型转换为整型时,舍去小数部分;②将整型转换为实数型时,数值不变,但将以实数型形式存放,即增加小数部分(小数部分的值为0);③将字符型转换为整型时,由于字符型为一个字节,而整型为两个字节,所以将字符的ASCII码值放到整型量的低8位中,高8位为0;④将整型转换为字符型时,只把低8位转换给字符变量。
【复合赋值运算符】 在赋值运算符“=”的前面加上其他运算符,就可构成复合赋值运算符。C 语言中的复合赋值运算符包括加法赋值运算符(+=)、减法赋值运算符(-=)、乘法赋值运算符(*=)、除法赋值运算符(/=)、求余(取模)赋值运算符(%=)、逻辑“与”赋值运算符(&=)、逻辑“或”赋值运算符(|=)、逻辑“异或”赋值运算符(^=)、逻辑“取反”赋值运算符(~=)、逻辑“左移”赋值运算符(<<=)、逻辑“右移”赋值运算符(>>=)共11种运算。
复合赋值运算首先对变量进行某种运算,然后再将运算的结果赋给该变量。采用复合赋值运算可以简化程序,同时提高C程序的编译效率。复合赋值运算表达式的一般格式为
例如:
3.关系运算符
在程序中,有时需要先对某些量的大小进行比较,然后根据比较的结果进行相应的操作。在C语言中,关系运算符专用于两个量的大小比较,其比较运算的结果只有“真”和“假”两个值。
C语言中的关系运算符包括大于(>)、小于(<)、等于(= = )、大于或等于(>=)、小于或等于(<=)、不等于(!=)共6种。
用关系运算符将两个表达式连接起来的式子称为关系表达式。关系运算符两边的运算对象可以是C语言中任意合法的表达式或变量。关系表达式的一般格式为
关系运算符的优先级别如下:①大于(>)、小于(<)、大于或等于(>=)、小于或等于(<=)属于同一优先级,等于(= = )、不等于(!=)属于同一优先级,其中前4种运算符的优先级高于后两种运算符的优先级;②关系运算符的优先级别低于算术运算符,但高于赋值运算符的优先级。例如:
关系运算符的结合性为左结合。C语言不像其他高级语言那样有专门的“逻辑值”,它用整数“0”和“1”来描述关系表达式的运算结果,规定用“0”表示逻辑“假”,即当表达式不成立时,运算结果为“0”;用“1”表示逻辑“真”,即当表达式成立时,运算结果为“1”。例如:
逻辑关系主要包括逻辑“与”、逻辑“或”、逻辑“非”这3种基本运算。在C语言中,用“&&”表示逻辑“与”运算;用“||”表示逻辑“或”运算;用“!”表示逻辑“非”运算。其中,“&&”和“||”是双目运算符,它要求有两个操作数,而“!”是单目运算符,只要求有一个操作数即可。
注意:
“&”和“|”是位运算符,不要将逻辑运算符与位运算符混淆。
用逻辑运算符将关系表达式或逻辑量连接起来的式子称为逻辑表达式。逻辑表达式的一般格式为
逻辑表达式的值是一个逻辑量,为“真”(即“1”)或“假”(即“0”)。对于逻辑“与”运算(&&)而言,参与运算的两个量都为“真”时,结果才为“真”,否则为“假”;对于逻辑“或”运算(||)而言,参与运算的两个量中只要有一个量为“真”时,结果为“真”,否则为“假”;对于逻辑“非”运算(!)而言,参与运算量为“真”时,结果为“假”,参与运算量为“假”时,结果为“真”。
逻辑运算符的优先级别如下:①在3个逻辑运算符中,逻辑“非”运算符(!)的优先级最高,其次是逻辑“与”运算符(&&)的优先级,逻辑“或”运算符(||)的优先级最低。②与算术运算符、关系运算符及赋值运算符的优先级相比,逻辑“非”运算符(!)的优先级高于算术运算符的优先级,算术运算符的优先级高于关系运算符的优先级,关系运算符的优先级高于逻辑“与”运算符(&&)和逻辑“或”运算符(||)的优先级,而赋值运算符的优先级最低。例如:
5.位操作运算符
能对运算对象进行位操作是C语言的一大特点,正是由于有这一特点,使C语言具有汇编语言的一些功能,从而使它能对计算机的硬件直接进行操作。
位操作运算符是指按位对变量进行运算,并不改变参与运算的变量的值。如果希望按位改变运算变量的值,则应利用相应的赋值运算。另外,位运算符只能对整型或字符型数据进行操作,不能用于对浮点型数据进行操作。
C语言中的位操作运算符包括按位“与”(&)、按位“或”(|)、按位“异或”(^)、按位“取反”(~)、按位“左移”(<<)、按位“右移”(>>)共6种运算。除了按位“取反”运算符外,其余5种位操作运算符都是双目运算符,即要求运算符两侧各有一个运算对象。
【按位“与”(&)】 按位“与”的运算规则是参加运算的两个运算对象,若二者相应的位均为“1”,则该位的结果为“1”,否则为“0”。
例如:若a=0x62=0b01100010,b=0x3c=0b00111100,则表达式c=a&b的值为0x20,即
【按位“或”( | )】 按位“或”的运算规则是参加运算的两个运算对象,若二者相应的位中只要有一位为“1”,则该位的结果为“1”,否则为“0”。
例如:若a=0xa5=0b10100101,b=0x29=0b00101001,则表达式c=a|b的值为0xad,即
【按位“异或”( ^ )】 按位“异或”的运算规则是参加运算的两个运算对象,若二者相应的位值相同,则该位的结果为“0”;若二者相应的位值相异,则该位的结果为“1”。
例如:若a=0xb6=0b10110110,b=0x58=0b01011000,则表达式c=a^b的值为0xee,即
【按位“取反”(~)】 按位“取反”(~)是单目运算,用于对一个二进制数按位进行“取反”操作,即“0”变“1”,“1”变“0”。
例如:若a=0x72=0b01110010,则表达式a=~a的值为0x8d,即
【按位“左移”( << )、按位“右移”( >> )】 按位“左移”(<<)用于将一个操作数的各二进制位的全部左移若干位,移位后,空白位补“0”,而溢出的位舍弃。
例如:若a=0x8b=0b10001011,则表达式a=a<<2表示将a值左移2位,其结果为0x2c,即
按位“右移”(>>)用于将一个操作数的各二进制位的全部右移若干位,移位后,空白位补“0”,而溢出的位舍弃。
例如:若a=0x8b=0b10001011,则表达式a=a>>2表示将a值右移2位,其结果为0x22,即
在ICCAVR中不能直接访问寄存器的某一位,因此对寄存器进行位操作时,需使用C语言中的位运算功能。在CodeVisionAVR中可以直接或间接操作寄存器的某一位,它可以直接对位进行置“1”或清“0”操作。
☺ 将寄存器的某一位清零,在 ICCAVR 中可使用按位“与”(&)来实现;在CodeVisionAVR中除了可以使用按位“与”(&)外,还可以直接将该位赋为“0”。
例如:将PC2清零,而其他位不变,以下3条指令均可实现该要求。
☺ 将寄存器的某一位置“1”,在 ICCAVR 中可使用按位“或”(|)来实现;在CodeVisionAVR中除了可以使用按位“或”(|)外,还可以直接将该位赋为“1”。
例如:将PC4置“1”,而其他位不变,以下3条指令均可实现该要求。
☺ 将寄存器的某一位“取反”,在 ICCAVR 中可使用按位“异或”(^)来实现;在CodeVisionAVR中除了可以使用按位“异或”(^)外,还可以直接将该位“取反”(~)。
例如:将PC6位“取反”,而其他位不变,以下3条指令均可实现该要求。
6.条件运算符
条件运算符是C语言中唯一的一个三目运算符,它要求有3个运算对象,用它可以将3个表达式连接起来构成一个条件表达式。条件表达式的一般格式为
条件表达式的功能是首先计算表达式1的逻辑值,当逻辑值为“真”时,将表达式2的值当做整个条件表达式的值;当逻辑值为“假”时,将表达式3的值当做整个条件表达式的值。例如:
7.逗号运算符
逗号运算符又称为顺序示值运算符。在C语言中,逗号运算符用于将两个或多个表达式连接起来。逗号表达式的一般格式为
逗号表达式的运算过程是,先求解表达式1,再求解表达式2,……依次求解到表达式n。例如:
8.求字节运算符
在C语言中提供了一种用于求取数据类型、变量及表达式的字节数的运算符sizeof。求字节运算符的一般格式为
注意:
sizeof是一种特殊的运算符,而不是一个函数。通常,字节数的计算在程序编译时就完成了,而不是在程序执行的过程中计算出来的。
9.指针和地址运算符
指针是C语言中一个十分重要的概念,CVAVR中专门规定了一种指针类型的数据。变量的指针就是该变量的地址,也可以说是一个指向某个变量的指针变量。CVAVR中提供了两个专门用于指针和地址的运算符,即*(取内容)和&(取地址)。
取内容和取地址的一般形式:
变量=*指针变量
指针变量=&目标变量
取内容运算是将指针变量所指向的目标变量的值赋给左边的变量;取地址运算是将目标变量的地址赋给左边的变量。