1.单目运算符
所谓单目运算符就是只接受一个操作数的运算符,他们是:
! ++ - & sizeof
~ -- + * (类型)
以下分别介绍他们的含义:
1.1逻辑取反(!) 与 按位取反(~)
!运算符是逻辑取反的意思,如果操作数为真(非零)则结果为假,如果操作数为假则结果为
真。由于C语言没有布尔值,所以它的结果实际上是整数,0或1.
~操作符对整型数据执行按位取反操作,即先把他们转换为二进制数,然后对各个位取反,原来为1的位转化为0,原来为0的位转化为1.
1.2求负运算符(-) 与 原值运算符(+)
-运算符(注意:是求负运算符不是减法运算符),其结果为原操作数的负值。
+运算符产生操作数本身的值,换言之,它不执行任何操作,仅仅为求负运算符(-)对应。
1.3取地址运算符(&) 与 间接访问运算符(*)
&运算符(注意:是取地址运算符不是位与运算符),意为取变量的地址
*运算符为间接访问运算符,它与指针一起使用,意为取指针所指向的变量的值。
【注意】
&操作符为取变量的地址,它不能作用在常量上。
1.4sizeof运算符
sizeof运算符意为判断操作数的类型长度,以字节为单位。
【注意】
(1)sizeof的操作数可以是变量、类型或表达式
(2)当sizeof作用于数组名时表示的是数组变量所占内存的长度(字节数)
(3)任何类型的指针的长度均相同,具体数值取决于你的环境,一般为4
具体实例如下:
1.5 (类型)运算符
(类型)运算符为强制类型转换符,它用于显式的把表达式的值转化为另外的类型。
1.6 自增运算符(++) 与 自减运算符(--)
++运算符与--运算符分别有两种形式:前缀与后缀。他们对操作数的要求是相同的,即操作数必须为左值。
++运算符和--运算符的结果为操作数的值,由于操作数在执行过++与--后值会发生变化,因此判断表达式取 变量之前的值 还是 执行过++或--之后的值至关重要。规则如下:
前缀++、前缀--操作符的执行结果为操作数变化后的值。--简记:先++或先--,再取值
后缀++、后缀--操作符的执行结果为操作数变化前的值。--简记:后++或后--,先取值
【注意】
++a、--a为右值:由前缀的含义可知,变量a先自身赋值,然后结果为表达式的值,表达式的值为右值。因此,++a = 10是错误的语法
a++、a--为左值:由后缀含义可以,先求表达式的值,后变量a自身的赋值,自身的赋值为左值。因此,a++ = 10是正确的语法。
2.位运算符
顾名思义,位运算符就是对二进制位的操作。
2.1左移、右移位运算符
左移(<<)、右移(>>)的特点:
(1)A 移位符 B表示A移位B个位数,其中移位符为“<<”、“>>”中一个。
(2)移位分为逻辑移位与算术移位,逻辑移位特点是一边移除,另一边补零。算术移位特点是一边移除,另一边补符号值(0或1),左移只有逻辑移位。右移有逻辑移位与算术移位之分。
(3)由于逻辑移位与算术移位的符号一样,所以决定是算术移位还是逻辑移位要看编译器的特性了。但是有一点,无符号数都是逻辑移位。
(4)程序中若使用了有符号数的右移,那么它是不可移植的,原因在于不同环境对右移的解释可能是逻辑的也可能是算术的,而有符号数算术右移和逻辑右移的结果是不一样的,所以不可移植。
【注意】
(1)判断程序是否可移植的一个重要原因就是移植前后各项的值是否保持不变。若不变,则可以移植;否则不可以移植。
(2)对于正整数的左移k位,并不一定都是增大为2^k倍,因为有可能在移位过程中将有效的1给移除。所以正整数左移K位增大为2^k倍的大前提是:有效位未被移除。
2.2位与(&)、位或(|)、异或(^)运算符
位与(&)特点:一零得零,全一得一。其主要应用于清零操作:不论另一位为何值,本位值只要为零与之执行位与操作该位结果必为零。
位或(|)特点:一一得一,全零得零。其主要应用与置一操作:不论另一位为何值,本位值只要为一与之执行位或操作该位结果必为一。
异或(^)特点:相同为零,不同为一。
3.条件运算符
条件运算符为三目运算符,它接收三个操作数,用法如下:
exp1 ? exp2 : exp3
它的含义为:首先计算exp1的值,当其值为真时结果为exp2的值;其值为假时则结果为exp3的值。
【总结】
条件运算符实现的功能与分支语句if...else...相同,虽然很多人认为条件运算符要好过if...else,因为它可以用更少的代码来实现if...else...的功能。但于我个人来说,我可能更倾向于if...else...。我觉得if...else...的扩展性更强。
4.逗号运算符
逗号运算符即将各个表达式用逗号分割,但整个表达式的结果为最后一个表达式的结果,逗号表达式的形式如下:
exp1,exp2,exp3...,exp
整个表达式的结果为exp的值。
【总结】
多个时候,逗号表达式并没有为程序带来方便,它计算了多个表达式的值,但只保留最后一个表达式的值作为最终的结果,带来了冗余的代码。但以下一种用法却体现了它独特的优越性:
/* 输入a的值,当a>0时循环输入a值直至a<=0时退出循环。 */
/* 第一种方法 */
a = getValue();
while(a > 0)
{
printf("a = %d\n",a);
a = getValue();
}
/* 第二种方法 */
while(a = getValue(),a > 0)
{
printf("a = %d\n",a);
}
很明显,用第二种方法比第一种方法更简便,因为它书写起来方便,尤其是程序中当涉及多个步骤对a求值时,第二种方法的优越性就更明显。
5.下标引用、函数调用、结构成员访问操作符
下标引用操作符有一下两种使用形式:
arr[i]
*(arr+i)
结构成员访问操作符用于对结构成员的访问,有一下两种方式:
.:.操作符为通过结构体名称访问结构成员
->:->操作符为通过指向结构体的指针访问结构成员。