运算符表达式和语句
1.基本运算符
-
=
- 数据对象:泛指数据在内存的存储区域
- 左值:表示可以被更改的数据对象
- 右值:能赋给左值的量
-
+:加
-
-:减
-
*:乘
-
/:除
-
%:取余数
-
+=:加等于
-
-=:减等于
-
*=:乘等于
-
/=:除等于
-
%=:取余等于
-
++:自加1
- i++先计算表达式的值,然后在++(加一)
- ++i是先++(加一),在计算表达式的值
-
--:自减1
-
逗号运算符
int a=2; int b=3; int c=4; int d=5; int i=(a=b,c+b); //逗号表达式先求逗号左边的值,然后求右边的值,整个语句的值是逗号右边的值运算符优先级
| 优先级 | 运算符 | 结合性 |
|---|---|---|
| 1 | ++(后缀),--(后缀),()(调用函数),{}(语句块),.,-> | 从左到右 |
| 2 | ++(前缀),--(前缀),+(前缀),-(前缀),!(前缀),~(前缀),sizeof,*(取指针值),&(取地址),(type)(类型转化) | 从右到左 |
| 3 | *, /, % | 从左到右 |
| 4 | +,- | 从左到右 |
| 5 | << >> | 从左到右 |
| 6 | < > <= >= | 从左到右 |
| 7 | == != | 从左到右 |
| 8 | & | 从左到右 |
| 9 | ^ | 从左到右 |
| 10 | | | 从左到右 |
| 11 | && | 从左到右 |
| 12 | || | 从左到右 |
| 13 | ? | 从右到左 |
| 14 | =,*=,%=,+=,-=,<<=,>>=,&=,|=,^= | 从右到左 |
| 15 | ,(逗号运算符) | 从左到右 |
- 复合语句
- {}代码块
- 空语句
- 只有一个;号的语句就是空语句,空语句在C语言里面和合法的,并且是在某些场合必用的
- 类型转换
- 隐式转换
- 强制转换
1、隐式类型转换
所谓隐式类型转换指的是,系统自动将取值范围小的数据类型转换为数据取值范围大的数据类型,它
是由系统自动转换完成的。例如,将 int 类型和 double 类型的数据相加,系统会将 int 类型的数据转换为
double 类型的数据,再进行相加操作,具体示例如下:
在 C 语言程序中,经常需要对不同类型的数据进行运算,为了解决数据类型不一致的问题,需要对数
据的类型进行转换。例如一个浮点数和一个整数相加,必须先将两个数转换成同一类型。C 语言程序中的
类型转换可分为隐式和强制类型转换两种,具体如下。
num1+num2;
(2)单、双精度浮点型
在上述示例代码中,由于 double 类型的取值范围大于 int 类型,因此,将 int 类型的 num1 与 double
类型的 num2 相加时,系统会自动将 num1 的数据类型由 int 转换为 double 类型,从而保证数据的精度不会
丢失。
double num2=10.5;
(int)x+y //将变量 x 的值转换成 int 后,在与 y 相加
在上述格式中,类型名和表达式都需要用括号括起来,具体示例如下:
由于 C 语言中的浮点值总是用双精度表示的,所以 float 型数据参与运算时只需要在尾部加 0 延长为
double 型数据。double 型数据转换为 float 型时,会造成数据精度丢失,有效位以外的数据将会进行四舍五
入。
(double)(x+y) //将表达式 x+y 的值转换成 double 类型
14
上述讲解的两种类型转换,看起来很简单,但在使用时有许多细节需要注意,具体如下:
(1)浮点型与整型
double x;
int y;
将浮点数(单双精度)转换为整数时,将舍弃浮点数的小数部分,只保留整数部分。将整型值赋给浮点
型变量,数值不变,只将形式改为浮点形式,即小数点后带若干个 0。需要注意的是,赋值时的类型转换
实际上是强制的。
int num1=12;
运算符
1.类型转换
(3)char 型与 int 型
将 int 型数值赋给 char 型变量时,只保留其最低 8 位,高位部分舍弃。
将 char 型数值赋给 int 型变量时, 一些编译程序不管其值大小都作正数处理,而另一些编译程序在转
换时会根据 char 型数据值的大小进行判断,若值大于 127,就作为负数处理。对于使用者来讲,如果原来
char 型数据取正值,转换后仍为正值。如果原来 char 型值可正可负,则转换后也仍然保持原值,只是数据
的内部表示形式有所不同。
(4)int 型与 long 型
long 型数据赋给 int 型变量时,将低 16 位值送给 int 型变量,而将高 16 位截断舍弃。(这里假定 int
型占两个字节)。 将 int 型数据送给 long 型变量时,其外部值保持不变,而内部形式有所改变。
(5)无符号整数
将一个 unsigned 型数据赋给一个长度相同的整型变量时(如:unsigned→int、unsigned long→long,
unsigned short→short) ,内部的存储方式不变,但外部值却可能改变。
将一个非 unsigned 整型数据赋给一个长度相同的 unsigned 型变量时, 内部存储形式不变,但外部表
示时总是无符号的。
运算符是编程语言中不可或缺的一部分,用于对一个或多个值(表达式)进行运算。本节将针对 C 语言
中的常见运算符进行详细地讲解。
在应用程序中,经常会对数据进行运算,为此,C 语言提供了多种类型的运算符,即专门用于告诉程
序执行特定运算或逻辑操作的符号。根据运算符的作用,可以将 C 语言中常见的运算符分为六大类,具体
如表 2-10 所示。
表2-10 常见的运算符类型及其作用
运算符类型 作用
算术运算符 用于处理四则运算
赋值运算符 用于将表达式的值赋给变量
比较运算符 用于表达式的比较,并返回一个真值或假值
逻辑运算符 用于根据表达式的值返回真值或假值
位运算符 用于处理数据的位运算
sizeof 运算符 用于求字节数长度
#include <stdio.h>
2 void main()
3 {
4 //通过类型名称计算各基本数据类型所占内存大小
5 printf("char: %d\n", sizeof(char));
6 printf("short: %d\n", sizeof(short));
7 printf("long: %d\n", sizeof(long));
8 printf("float: %d\n", sizeof(float));
9 printf("double: %d\n", sizeof(double));
10 printf("unsigned char: %d\n", sizeof(unsigned char));
11 printf("unsigned short: %d\n", sizeof(unsigned short));
12 printf("unsigned int: %d\n", sizeof(unsigned int));
13 printf("unsigned long: %d\n", sizeof(unsigned long));
14 //通过变量名称计算变量所属数据类型占用内存大小
15 int val_int = 100;
16 double val_double = 100000.0;
17 printf("val_int: %d\n", sizeof(val_int));
18 printf("val_double: %d\n", sizeof(val_double));
19 }
表 2-10 列举了 C 语言中常用的运算符类型,并且每种类型运算符的作用都不同。运算符是用来操作
数据的,因此,这些数据也被称为操作数,使用运算符将操作数连接而成的式子称为表达式。表达式具有
如下特点:
1、 常量和变量都是表达式,例如,常量 3.14、变量 i。
2、 运算符的类型对应表达式的类型,例如,算术运算符对应算术表达式。
3、每一个表达式都有自己的值,即表达式都有运算结果。
2.运算符
2.1 运算符与表达式
在数学运算中最常见的就是加减乘除四则运算。C 语言中的算术运算符就是用来处理四则运算的符号,
这是最简单、最常用的运算符号。表 2-11 列出了 C 语言中的算术运算符及其用法。
表2-11 算术运算符
运算符 运算 范例 结果
- 正号 +3 3
- 负号 b=4;-b; -4
- 加 5+5 10
- 减 6-4 2
-
乘 3*4 12
/ 除 5/5 1
% 取模(即算术中的求余数) 7%5 2
++ 自增(前) a=2;b=++a; a=3;b=3;
++ 自增(后) a=2;b=a++; a=3;b=2;
-- 自减(前) a=2;b=--a; a=1;b=1;
-- 自减(后) a=2;b=a--; a=1;b=2;
算术运算符看上去都比较简单,也很容易理解,但在实际使用时还有很多需要注意的问题,接下来就
针对其中比较重要的几点进行详细地讲解,具体如下:
1、进行四则混合运算时,运算顺序遵循数学中“先乘除后加减”的原则。
2、在进行自增(++)和自减(--)的运算时,如果运算符(++或--)放在操作数的前面则是先进行自
增或自减运算,再进行其他运算。反之,如果运算符放在操作数的后面则是先进行其他运算再进行自增或
自减运算。
请仔细阅读下面的代码块,思考运行的结果。int num1 = 1; int num2 = 2; int res = num1 + num2++; printf("num2=%d" + num2); printf("res=%d" + res);上面的代码块运行结果为:num2=3,res=3,具体分析如下:
第一步:运算 mum1+mun2++的结果,此时变量 mun1,mum2 的值不变。
第二步:将第一步的运算结果赋值给变量 res,此时 res 值为 3。
第三步:mum2 进行自增,此时其值为 3。
3、在进行除法运算时,当除数和被除数都为整数时,得到的结果也是一个整数。如果除法运算有浮
点数参与运算,系统会将整数数据隐形类型转换为浮点类型,最终得到的结果会是一个浮点数。例如,
2510/1000 属于整数之间相除,会忽略小数部分,得到的结果是 2,而 2.5/10 的实际结果为 0.25。
请思考一下下面表达式的结果:
3500/10001000
结果为 3000。由于表达式的执行顺序是从左到右,所以先执行除法运算 3500/1000,得到结果为 3,
然后再乘以 1000,最终得到的结果自然就是 3000。
4、取模运算在程序设计中都有着广泛的应用,例如判断奇偶数的方法就是求一个数字除以 2 的余数是
1 还是 0。在进行取模运算时,运算结果的正负取决于被模数(%左边的数)的符号,与模数(%右边的数)的
2.2 算术运算符
符号无关。如:(-5)%3=-2,而 5%(-3)=2。
赋值运算符的作用就是将常量、变量或表达式的值赋给某一个变量。表 2-12 列举了 C 语言中的赋值
运算符及其用法。
表2-12 赋值运算符
运算符 运算 范例 结果
= 赋值 a=3;b=2; a=3;b=2;
+= 加等于 a=3;b=2;a+=b; a=5;b=2;
-= 减等于 a=3;b=2;a-=b; a=1;b=2;
= 乘等于 a=3;b=2;a=b; a=6;b=2;
/= 除等于 a=3;b=2;a/=b; a=1;b=2;
%= 模等于 a=3;b=2;a%=b; a=1;b=2;
在表 2-12 中,“=”的作用不是表示相等关系,而是赋值运算符,即将等号右侧的值赋给等号左侧的
变量。在赋值运算符的使用中,需要注意以下几个问题:
1、在 C 语言中可以通过一条赋值语句对多个变量进行赋值,具体示例如下:
int x, y, z;
x = y = z = 5; //为三个变量同时赋值
在上述代码中,一条赋值语句可以同时为变量 x、y、z 赋值,这是由于赋值运算符的结合性为“从右
向左”,即先将 5 赋值给变量 z,然后再把变量 z 的值赋值给变量 y,最后把变量 y 的值赋值变量 x,表达
式赋值完成。需要注意的是,下面的这种写法在 C 语言中是不可取的。
int x = y = z = 5; //这样写是错误的
2、在表 2-12 中,除了“=”,其他的都是特殊的赋值运算符,接下来以“+=”为例,学习特殊赋值运算符的
用法,示例代码如下:
int x=2;
x+=3;
上述代码中,执行代码 x += 3 后,x 的值为 5。这是因为在表达式 x+=3 中的执行过程为:
(1)将 x 的值和 3 的执行相加。
(2)将相加的结果赋值给变量 x。
所以,表达式 x=+3 就相当于 x = x + 3,先进行相加运算,在进行赋值。-=、=、/=、%=赋值运算符
都可依此类推。
2.3 赋值运算符
比较运算符用于对两个数值或变量进行比较,其结果是一个逻辑值(“真”或“假”),如“5>3”,其值为
“真”。
C 语言的比较运算中,“真”用数字“1”来表示,“假”用数字“0”来表示。表 2-13 列出了 C 中的比较运算
符及其用法。
表2-13 比较运算符
运算符 运算 范例 结果
== 相等于 4 == 3 0
!= 不等于 4 != 3 1
< 小于 4 < 3 0
大于 4 > 3 1
<= 小于等于 4 <= 3 0
= 大于等于 4 >= 3 1
需要注意的是,在使用比较运算符时,不能将比较运算符“”误写成赋值运算符“=”。
逻辑运算符用于判断数据的真假,其结果仍为“真”或“假”。表 2-14 列举了 C 语言中的逻辑运算符及其
范例。
表2-14 逻辑运算符
运算符 运算 范例 结果
! 非 !a
如果 a 为假,则!a 为真;
如果 a 为真,则!a 为假
&& 与 a&&b 如果 a 和 b 都为真,则结果为真否则为假
|| 或 a|| b
如果 a 和 b 有一个或以上为真,则结
果为真,二者都为假时,结果为假
当使用逻辑运算符时,有一些细节需要注意,具体如下:
1、逻辑表达式中可以包含多个逻辑运算符,例如,!a||a>b
2、三种逻辑运算符的优先级从高到低依次为:!、&&、||
3、运算符“&&”表示与操作,当且仅当运算符两边的表达式结果都为真时,其结果才为真,否则结果
为假。如果左边为假,那么右边表达式是不会进行运算的,具体示例如下:
a+b<c&&cd
若 a=5,b=4,c=3,d=3,由于 a+b 的结果大于 c,表达式 a+b<c 的结果为假,因此,右边表达式 cd
不会进行运算,表达式 a+b<c&&cd 的结果为假。
4、运算符“||”表示或操作,当且仅当运算符两边的表达式结果都为假时,其结果为假。同“&&”运算
符类似,如果运算符“||”左边操作数的结果为真,右边表达式是不会进行运算的,具体示例如下:
a+b<c||cd
若 a=1,b=2,c=4,d=5,由于 a+b 的结果小于 c,表达式 a+b<c 的结果为真,因此,右边表达式 cd
不会进行运算,表达式 a+b<c||c==d 的结果为真。
2.4 比较运算符
2.5 逻辑运算符
位运算符是针对二进制数的每一位进行运算的符号,它是专门针对数字 0 和 1 进行操作的。C 语言中
的位运算符及其范例如表 2-1515 所示。
表2-15 位运算符
运算符 运算 范例 结果
& 按位与
0 & 0 0
0 & 1 0
1 & 1 1
1 & 0 0
| 按位或
0 | 0 0
0 | 1 1
1 | 1 1
1 | 0 1
~ 取反 ~0 1
~ 1 0
^ 按位异或
0 ^ 0 0
0 ^ 1 1
1 ^ 1 0
1 ^ 0 1
<< 左移 00000010<<2 00001000
10010011<<2 01001100右移 01100010>>2 00011000
11100010>>2 11111000
接下来通过一些具体示例,对表 2-15 中描述的位运算符进行详细介绍,为了方便描述,下面的运算都
是针对 byte 类型的数,也就是 1 个字节大小的数。
1、 与运算符“&”是将参与运算的两个二进制数进行“与”运算,如果两个二进制位都为 1,则该位的
运算结果为 1,否则为 0。
例如将 6 和 11 进行与运算, 6 对应的二进制数为 00000110,11 对应的二进制数为 00001011,具
体演算过程如下所示:
00000110
&
00001011
—————————
00000010
运算结果为 00000010,对应数值 2。
2、 位运算符“|”是将参与运算的两个二进制数进行“或”运算,如果二进制位上有一个值为 1,则该
位的运行结果为 1,否则为 0。具体示例如下:
例如将 6 与 11 进行或运算,具体演算过程如下:
00000110
|
00001011
—————————
00001111
2.6 位运算符
运算结果为 00001111,对应数值 15。
3、 位运算符“~”只针对一个操作数进行操作,如果二进制位是 0,则取反值为 1;如果是 1,则取
反值为 0。
例如将 6 进行取反运算,具体演算过程如下:
~ 00000110
—————————
11111001
运算结果为 11111001,对应数值-7。
4、 位运算符“^”是将参与运算的两个二进制数进行“异或”运算,如果二进制位相同,则值为 0,否
则为 1。
例如将 6 与 11 进行异或运算,具体演算过程如下:
00000110
^
00001011
—————————
00001101
运算结果为 00001101,对应数值 13。
5、 位运算符“<<”就是将操作数所有二进制位向左移动一位。运算时,右边的空位补 0。左边移走
的部分舍去。
例如一个 byte 类型的数字 11 用二进制表示为 00001011,将它左移一位,具体演算过程如下:
00001011 <<1
—————————
00010110
运算结果为 00010110,对应数值 22。
6、 位运算符“>>”就是将操作数所有二进制位向右移动一位。运算时,左边的空位根据原数的符号
位补 0 或者 1(原来是负数就补 1,是正数就补 0)。
例如一个 byte 的数字 11 用二进制表示为 00001011,将它右移一位,具体演算过程如下:
00001011 >>1
—————————
00000101
运算结果为 00000101,对应数值 5。
同一种数据类型在不同的编译系统中所占空间不一定相同,例如,在基于 16 位的编译系统中,int 类
型占用 2 个字节,而在 32 位的编译系统中,int 类型占用 4 个字节。为了获取某一数据或数据类型在内存
中所占的字节数,C 语言提供了 sizeof 运算符,使用 sizeof 运算符获取数据字节数,其基本语法规则如下
所示:
sizeof(数据类型名称);
或
sizeof(变量名称);
为了帮助大家更好地学习 sizeof 运算符,接下来,通过一个案例来计算每种数据类型所占内存的大小,
具体如例 2-7 所示。
例2-7
2.7 sizeof 运算符
1
运行结果如图 2-12 所示。
图2-12 运行结果
从图 2-12 中可以看出,不同数据类型在内存中所占字节数都打印了出来,由此可见,使用 sizeof 关键
字可以很方便地获取到数据或数据类型在内存中所占的字节数。
在对一些比较复杂的表达式进行运算时,要明确表达式中所有运算符参与运算的先后顺序,我们把这
种顺序称作运算符的优先级。表 2-16 列出了 C 语言中运算符的优先级,数字越小优先级越高。
表2-16 运算符优先级
优先级 运算符
1 . [] ()
2 ++ -- ~ ! (数据类型)
3 * / %
2.8 运算符的优先级
4 + -
5 << >> >>>
6 < > <= >=
7 == !=
8 &
9 ^
10 |
11 &&
12 ||
13 ?:(三目运算符)
14 = = /= %= += -= <<= >>= >>>= &= ^= |=
根据表 2-16 所示的运算符优先级,分析下面代码的运行结果。
int a =2;
int b = a + 3a;
printf ("%d",b);
以上代码的运行结果为 8,这是由于运算符“”的优先级高于运算符“+”,因此先运算 3a,得到的结果
是 6,再将 6 与 a 相加,得到最后的结果 8。
int a =2;
int b = (a+3) * a;
printf ("%d",b);
以上代码的运行结果为 10,这是由于运算符“()”的优先级最高,因此先运算括号内的 a+3,得到的
结果是 5,再将 5 与 a 相乘,得到最后的结果 10。
其实没有必要去刻意记忆运算符的优先级。编写程序时,尽量使用括号“()”来实现想要的运算顺序,
以免产生歧义。
多学一招:单目、双目、三目运算符
在 C 语言中根据运算符进行运算需根据变量的个数可以将运算符分为单目运算符、双目运算符和三目
运算符,具体如表 2-17 所示。
表2-17 单目、双目、三目运算符的比较
名称 运算所需变量个数 范例
单目运算符 1 个 ++、--、!、sizeof、~、…
双目运算符 2 个 +、-、*、/、%、<<、==、…
三目运算符 3 个 ?:
在表 2-17 中单目运算符的优先级高于双目运算符和三目运算符。三目运算符“?:”用于条件判断的情况,
读者在这只需了解即可,在后面的章节中将会进行详细讲解。

浙公网安备 33010602011771号