运算符 | 进行的运算 | 所属类别 | 备注 |
[ ] | 间隔符 | 标点符号 | |
( ) | 间隔符 | 标点符号 | |
· | 直接分量选择 | 双目操作符 | |
-> | 间接分量选择 | 双目操作符 | |
++ | 前增量、后增量 | 单目操作符 | |
-- | 前减量、后减量 | 单目操作符 | |
+ | 加 | 双目操作符、单目操作符 | |
- | 减 | 双目操作符、单目操作符 | |
* | 1)乘 2)间接引用 | 双目操作符、单目操作符 | |
/ | 除 | 双目操作符 | |
% | 求余 | 双目操作符 | |
& | 1)位‘与’2)取地址 | 双目操作符、单目操作符 | |
! | 逻辑‘非’ | 单目操作符 | |
&& | 逻辑‘与’ | 双目操作符 | |
|| | 逻辑‘或’ | 双目操作符 | |
<< | 左移位 | 双目操作符 | |
>> | 右移位 | 双目操作符 | |
< | 小于 | 双目操作符 | |
> | 大于 | 双目操作符 | |
== | 等于 | 双目操作符 | |
!= | 不等于 | 双目操作符 | |
^ | 位‘异或’ | 双目操作符 | |
+= | 和赋值 | 双目操作符 | |
-= | 差赋值 | 双目操作符 | |
*= | 乘赋值 | 双目操作符 | |
/= | 商赋值 | 双目操作符 | |
<<= | 左移赋值 | 双目操作符 | |
>>= | 右移赋值 | 双目操作符 | |
&= | 按位‘与’赋值 | 双目操作符 | |
^= | 按位异或赋值 | 双目操作符 | |
|= | 按位或赋值 | 双目操作符 | |
%= | 模赋值 | 双目操作符 | |
= | 赋值 | 双目操作符 | |
?: | 按条件取值 | 双目操作符 | |
, | 间隔符 | 标点符号 | |
# | 预处理符号 | 标点符号 | |
## | 预处理符号 | 标点符号 | |
sizeof | 求字节数 | ||
~ | 按位求反 | ||
| | 位‘或’ | ||
: | 间隔符 | ||
; | 间隔符 | ||
... | 间隔符 | ||
要把表中的运算符仔细的分类是不容易的,因为同一个运算符,在不同的地方其含义是不同的。如*运算符,当作为乘运算时是双目操作符(所谓双目操作符,即运算时需要二个操作数),如3*6,那么3与6总共是二个操作数。当作为取值运算时就是单目操作符(所谓单目操作符是只需要一个操作数)如对一个数求反:!a,这里只有一个操作数a。
要记住运算符的二个特点,一个是运算符的操作对象,另一个就是运算符的优先级别。其中运算符的优先级别是最不容易搞清楚和最容易出错的地方。
在讲运算符之前讲一下“表达式”的概念:所谓表达式,就是用运算符把各个操作数连接成符合C语法规则的进行运算的式子。这里说的“符合C语法的规则”也很重要。如 a+b+5就是一个用算术运算符连接起来的表达式。
1、算术运算符:+、-、*、/、%
1)+、-、*、/ 分别是相加、相减、相乘、相除
2)% 求二个数运算的模。所谓求模就是求二个数相除后的余数。例:25/3的余数是1,可以说25%3的模是1。要注意的是求模运算时二个操作数必须是整数。如果求25.3/3.1这样是不能运算的。
下面写一个例子:
#include<stdio.h> /*程序中要用到输入输出库函数,所以包含了stdio.h*/
void main()
{
int a=10,b=20,c=30; /*定义了3个整型变量,并同时进行了初始化赋值*/
a=a*b+c; /*a*b+c组成了一个算术表达式,运算后的结果为230并把值*/
/*赋给变量a*/
printf("%d",a); /*以整型格式输出变量a的值。这里输出230*/
a=a%b; /*进行求模运算。因为没有余数,最后的模为0*/
printf("%d",a); /*输出变量a的值。这里输出0*/
}
下面是一个要考虑运算符优先级的例子:
#include<stdio.h>
void main()
{
int a=10,b=20,c=30;
a=c-a*b; /*这里就要考虑运算符优先级,*运算符的优先级比-运算符*/
/*的高,所以先进行乘运算。这里最后结果为-170*/
}
由上面这个例子看到,在一个有多个运算符连接起来的表达式中需要考虑运算符的优先级,这个例子很简单。关于运算符优先级的概念其实在小学生的算术运算中就有这样的概念了,只不过这里的运算符多了一些,要考虑的情况也就复杂了。
如果这个式子改写一下,写成:a=(c-a)*b;在运算时就以括号中的运算优先。
几个简化的运算表达式:
在C语言的程序中,经常看到这样的运算,如:i++;或者k--;这是运算符号的简化写法。
1、加1运算的简写
当一个变量进行加1运算时,如a=a+1;这是变量自身加1,简写为a++;
2、减1运算的简写
当一个变量进行减1运算时,如a=a-1;这是变量自身减1,简写为a--;
3、加1个常量运算的简写
当一个变量与一个常量相加时,如a=a+5;这是变量自身加5,简写为a+=5;
4、减一个常量运算的简写
当一个变量与一个常量相减时,如a=a-5;这是变量自身减5,简写为a-=5;
5、乘一个常量运算的简写
当一个变量与一个常量相乘时,如a=a*5,这是变量自身乘5,简写为a*=5;
6、除一个常量运算的简写
当一个变量与一个常量相除时,如a=a/5;这是变量自身除5,简写为a/=5;
运算符的结合性(或称作关联性)
在一个复杂的表达式中,常常有许多运算符和变量,这时就要判断优先级和结合性这二个因素。
例:-5+7; 这样的一个表达式用结合性来判断,因为运算符'-'和'+'相对于运算的数来说是‘左’结合的,所以就有'-5'和'+7'所以运算的结果为 2。
通过这个例子要知道什么是“左结合性”和“右结合性”
左结合性--变量(或常量)与左边的运算符结合
右结合性--变量(或常量)与右边的运算符结合
运算符的优先级和结合性表
优先级 | 运算符(高 ------→低) | 结合率 | 运算符类型 | |
高 | ( ) [ ] -> . | 从左至右 | 双目运算符 | |
! ~ ++ -- (类型) sizeof + - * & | 从右至左 | 单目运算符 | ||
* / % | 从左至右 | 双目运算符 | ||
+ - | 从左至右 | 双目运算符 | ||
<< >> | 从左至右 | 双目运算符 | ||
< <= > >= | 从左至右 | 双目运算符 | ||
== != | 从左至右 | 双目运算符 | ||
& | 从左至右 | 双目运算符 | ||
^ | 从左至右 | 双目运算符 | ||
| | 从左至右 | 双目运算符 | ||
&& | 从左至右 | 双目运算符 | ||
|| | 从左至右 | 双目运算符 | ||
?: | 从右至左 | 三目运算符 | ||
低 | = += -= *= /= %= &= ^= |= <<= >>= | 从左至右 | 双目运算符 | |
高 -------------→ 低 |
从表中可以看出一个规律,凡是单目运算符都是“右结合”的,凡是双目运算符都是“左结合”的。其中有一个?:运算符是三目运算符是右结合的,记住了这个规律,运算符的结合性也就掌握了。
如果代码行中的运算符比较多,用括号确定表达式的操作顺序,避免使用默认的优先级。
由于将表熟记是比较困难的,为了防止产生歧义并提高可读性,应当用括号确定表达式的操作顺序。例如:
d = (high << 8) | low /*用括号把需要先运算的括起来*/
if ((a | b) && (a & c)) /*用括号把需要先运算的括起来*/
例:
下列程序输出的结果是
#include<stdio.h>
void main()
{
int a=2;
a%=4-1;
printf("%d",a);
a+=a*=a-=a*=3;
printf("\n%d",a);
}
A. 2,0 B. 1,0
C. -1,12 D. 2,12
分析:由于%=运算符的优先级别低于-运算,a%=4-1即是a%=3,等价于a=a%3即a=2%3=2,所以选项B和C是错误的。表达式a+=a*=a-=a*=3,计算时注意赋值类表达式的值和变量的值随时被更新,计算表达式的值,开始时a=2,表达式赋值是从左至右进行的,表达a*=3使得a=6,此表达式的值也为6,于是表达式a-=a*=3相当于a-=6=6-6=0,a的值为0,后面的计算就不用做了,所以a的值最终为0。
答:A
下列语句中错误的是
A.x=sizeof int;
B.x=sizeof 3.14
C.printf("%d",a=a+1,b--,c+1);
D.printf("%d",++x,x++);
分析:此题的选项A的作用是测试int类型所占内存的字节数,因为类型符要用括号括起来,这时缺少括号是错误的。
选项B是正确的。
选项C从表面上看似乎复杂一些,但其中的a=a+1,b--,c+1是一个逗号表达式,C语言允许使用这种表达式所以D也是正确的。
答案:A
下面的语句中,符合C语言语法的赋值语句是
A.a=7+b+c=a+7; B.a=7+b++=a+7;
C.a=7+b,b++,a+7; D.a=7+b;c=a+7;
分析:一般情况下,表达式不能放在赋值号的左边,所以A和B选项是错误的。
选项C不是一个C语言的语句,因为它不是以分号作为结束标志的。
答:D