5.1 循环简介
5.2 基本运算符(operator)
C用运算符(operator)表示算术运算。
算术运算符(来自菜鸟教程)
下表显示了 C 语言支持的所有算术运算符。假设变量 A 的值为 10,变量 B 的值为 20,则:
运算符 | 描述 | 实例 |
---|---|---|
+ | 把两个操作数相加 | A + B 将得到 30 |
- | 从第一个操作数中减去第二个操作数 | A - B 将得到 -10 |
* | 把两个操作数相乘 | A * B 将得到 200 |
/ | 分子除以分母 | B / A 将得到 2 |
% | 取模运算符,整除后的余数 | B % A 将得到 0 |
++ | 自增运算符,整数值增加 1 | A++ 将得到 11 |
-- | 自减运算符,整数值减少 1 | A-- 将得到 9 |
实例
请看下面的实例,了解 C 语言中所有可用的算术运算符:
#include <stdio.h>
int main()
{
int a = 21;
int b = 10;
int c ;
c = a + b;
printf("Line 1 - c 的值是 %d\n", c );
c = a - b;
printf("Line 2 - c 的值是 %d\n", c );
c = a * b;
printf("Line 3 - c 的值是 %d\n", c );
c = a / b;
printf("Line 4 - c 的值是 %d\n", c );
c = a % b;
printf("Line 5 - c 的值是 %d\n", c );
c = a++; // 赋值后再加 1 ,c 为 21,a 为 22
printf("Line 6 - c 的值是 %d\n", c );
c = a--; // 赋值后再减 1 ,c 为 22 ,a 为 21
printf("Line 7 - c 的值是 %d\n", c );
}
实例结果:
5.2.1 赋值运算符: = (初学时易混淆)
在C语言中,= 不表示相等,而是赋值。
如: i = i+1 表示把i+1的值 赋值给变量i
如果出现多重赋值: c = b = a = 12; 赋值的顺序是从右往左,先把12赋值给a,然后赋值给b
几个概念:
数据对象(data object):用于储存值的数据存储区域。
左值(lvalue) :用于标识和定位存储位置的标签。
右值(rvalue): 能赋值给可修改左值的量。
5.2.2 加法运算符:+
5.2.3 减法运算符:-
5.2.4 符号运算符:- 和+
// +为(C99)新增,然而似乎+符号并没有什么用,它不会改变运算对象的符号。
5.2.5 乘法运算符 :*
5.2.6 除法运算符:/
注意整数除法的小数部分会被丢弃(而不是四舍五入),如5/3 = 1。有浮点数的除法会有小数部分。
截断:在C语言里,整数除法结果的小数部分被丢弃
5.2.7 运算符优先级
优先级 | 运算符 | 名称或含义 | 使用形式 | 结合方向 | 说明 |
1 | [] | 数组下标 | 数组名[常量表达式] | 左到右 | -- |
() | 圆括号 | (表达式)/函数名(形参表) | -- | ||
. | 成员选择(对象) | 对象.成员名 | -- | ||
-> | 成员选择(指针) | 对象指针->成员名 | -- | ||
2 | - | 负号运算符 | -表达式 | 右到左 | 单目运算符 |
~ | 按位取反运算符 | ~表达式 | |||
++ | 自增运算符 | ++变量名/变量名++ | |||
-- | 自减运算符 | --变量名/变量名-- | |||
* | 取值运算符 | *指针变量 | |||
& | 取地址运算符 | &变量名 | |||
! | 逻辑非运算符 | !表达式 | |||
(类型) | 强制类型转换 | (数据类型)表达式 | -- | ||
sizeof | 长度运算符 | sizeof(表达式) | -- | ||
3 | / | 除 | 表达式/表达式 | 左到右 | 双目运算符 |
* | 乘 | 表达式*表达式 | |||
% | 余数(取模) | 整型表达式%整型表达式 | |||
4 | + | 加 | 表达式+表达式 | 左到右 | 双目运算符 |
- | 减 | 表达式-表达式 | |||
5 | << | 左移 | 变量<<表达式 | 左到右 | 双目运算符 |
>> | 右移 | 变量>>表达式 | |||
6 | > | 大于 | 表达式>表达式 | 左到右 | 双目运算符 |
>= | 大于等于 | 表达式>=表达式 | |||
< | 小于 | 表达式<表达式 | |||
<= | 小于等于 | 表达式<=表达式 | |||
7 | == | 等于 | 表达式==表达式 | 左到右 | 双目运算符 |
!= | 不等于 | 表达式!= 表达式 | |||
8 | & | 按位与 | 表达式&表达式 | 左到右 | 双目运算符 |
9 | ^ | 按位异或 | 表达式^表达式 | 左到右 | 双目运算符 |
10 | | | 按位或 | 表达式|表达式 | 左到右 | 双目运算符 |
11 | && | 逻辑与 | 表达式&&表达式 | 左到右 | 双目运算符 |
12 | || | 逻辑或 | 表达式||表达式 | 左到右 | 双目运算符 |
13 | ?: | 条件运算符 | 表达式1? 表达式2: 表达式3 | 右到左 | 三目运算符 |
14 | = | 赋值运算符 | 变量=表达式 | 右到左 | -- |
/= | 除后赋值 | 变量/=表达式 | -- | ||
*= | 乘后赋值 | 变量*=表达式 | -- | ||
%= | 取模后赋值 | 变量%=表达式 | -- | ||
+= | 加后赋值 | 变量+=表达式 | -- | ||
-= | 减后赋值 | 变量-=表达式 | -- | ||
<<= | 左移后赋值 | 变量<<=表达式 | -- | ||
>>= | 右移后赋值 | 变量>>=表达式 | -- | ||
&= | 按位与后赋值 | 变量&=表达式 | -- | ||
^= | 按位异或后赋值 | 变量^=表达式 | -- | ||
|= | 按位或后赋值 | 变量|=表达式 | -- | ||
15 | , | 逗号运算符 | 表达式,表达式,… | 左到右 | -- |
同一优先级的运算符,运算次序由结合方向所决定。
简单记就是:! > 算术运算符 > 关系运算符 > && > || > 赋值运算符
5.2.8 优先级和求值顺序
优先级高的先算,(优先级)相同的按照结合律
由于()优先级最高,我们只要把想先计算的用() 括起来就行了。
5.3 其他运算符
5.3.1 sizeof运算符和size_t 类型
sizeof运算符:以字节为单位返回运算对象的大小
用法 sizeof (int); sizeof n; //类型必须加() ,变量()可以不加
sizeof返回值是一个 size_t 类型的值, 可使用%zd或%u显示size_t类型的值
size_t 是一个无符号整数类型 ,是用typedef给无符号整数起的别名。
5.3.2 求模运算符: %(取余)
(只能)用于整数运算,取余数 (左边除以右边的余数)。
13%5 = 3
5.3.3 递增运算符++
a++; 相当于 a= a+1;
有两种形式前缀++a和后缀a++。
5.3.4 递减运算符--
5.3.5 优先级
++、--优先级较高,只低于()
5.3.6不要自作聪明
不要使用++ --的情形:
1.一个变量出现在一个函数的多个参数中
2.多次出现在一个表达式中
5.4 表达式和语句
5.4.1 表达式
表达式 (expression)由 运算符和运算对象组成。
例如:
4
4+2
q = 5
q > 3
......
每个表达式都有一个值
5.4.2 语句
语句(statement)是C程序的基本构建模块,
大多数语句都以 ; 结尾。
副作用和表达式 //可帮助理解执行顺序,看不懂就跳过。
副作用(side effect)是对数据对象或文件的修改
states = 50;
副作用是让state的值为50。 从C语言的角度看,主要目的是对表达式求值,而赋值表达式的副作用是让变量的值改变。
序列点(sequence point)是程序执行的点。 在该点上,所有副作用都在进入下一步之前发生。
在C语言中,分号标记一个序列点。一个完整表达式的结束也是一个序列点。
完整表达式指的是这个表达式不是另一个表达式的子表达式。
以下了解:
副作用:副作用在这里是指除了函数主要目的(格式化输出)之外的其他影响。 printf 的主要目的是将内容显示出来,而返回值(待显示字符的个数)虽然是一个有用的信息,但在很多简单的使用场景下,这个返回值往往被忽略。
比如在大多数基本的输出操作中,我们只是关心把内容正确地显示在屏幕上,像 printf("The result is: %d", result); ,重点是显示出结果的值,而不是 printf 返回的字符数。
但是在一些特殊的编程场景下,这个返回值可能会被用到。例如在编写一个复杂的文本处理程序,需要精确统计已经输出的字符数量时,就会用到 printf 的返回值。不过在一般的使用中,它相对输出显示这个主要功能而言,像是一个额外的、不太被关注的“副作用”。
序列点:在 C 和 C++等编程语言中,序列点是程序执行中的一个特定位置,在这个位置上,之前的副作用(如对变量的赋值等操作)必须完成,并且在此之后的操作不能重新排列到这个序列点之前。
5.4.3 复合语句(块)
复合语句块是花括号{}括起来的多条语句。
5.5类型转换
当类型不匹配时,C语言会自动进行基本的类型转换。
类型转换规则:
1.当类型转换出现在表达式时,无论是unsigned还是signed的char和short都会被自动转换为成int
2.涉及到两种类型的运算,两个值会被分别转换成两种类型的最高级别
3.类型的级别:
数据类型 | 等级 |
---|---|
long double | 高 |
double | |
float | |
unsigned long long | |
long long | |
unsigned long | |
long | |
unsigned int | |
int | 低 |
PS: short 和 char 类型在类型转换时会被自动转换为 int ,如有必要会被转换成 unsigned int (如果 short 和 int 的大小相同, unsigned short 就比 int 大。这种情况下, unsigned short 会被转换成 unsigned int)。另外当long和int的大小相同时,unsigned int 比 long 的级别高。
4.在赋值表达式语句中,计算机的最终结果会被转换成被赋值变量的类型。 将一种类型转换成更高级别的类型称为“升级”;将一种类型转换成更低级别的类型称为“降级”。
5.当作为函数参数传递时,char和short被转换成int,float被转换成double。
5.5.1 强制类型转换
通常应该避免自动类型转换。使用强制类型转换可以主动将某个量转换成目标类型。
使用强制类型转换符: (type )
举例:mice = (int)1.6 + (int)1.7;
5.6 带参数的函数
实参:
在调用有参函数时,函数名后面括号中的参数称为“实参”,是我们真实传给函数的参数,实参可以是:常量、变量、表达式、函数等。
无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。
形参:
形式参数是指函数名后括号中的变量,因为形式参数只有在函数被调用的过程中才实例化(分配内存单元),所以叫形式参数。
形式参数当函数调用完成之后就自动销毁了。因此形式参数只在函数中有效。