C语言基础,运算符基础知识总结(附习题)

1. 算术运算符

运算符术语示例结果
+正号+33
-负号-3-3
+10 + 515
-10 - 55
*10 * 550
/10 / 52
%取余(取模 Modulo)10 % 31
// 目标:掌握算数运算的基本语法
int main(void)
{
	int m = +3;
	int n = -3;
	printf("m=%d, n=%d\n", m, n);

	int a = 10, b = 5;
	printf("a+b=%d\n", a + b);
	printf("a-b=%d\n", a - b);
	printf("a*b=%d\n", a * b);
	printf("a/b=%d\n", a / b);
	printf("10%%3=%d\n", 10 % 3);  // 在printf的格式串中显示 %号, 需要使用 %%

	// 3 % 10 取余结果是多少呢?
	printf("3%%10=%d\n", 3 % 10);  // 3
    
	return 0;
}

注意事项

  1. 先 * / %,后 + -。
  2. 除法
    • 两整数相除,结果整数(舍小数部分)
    • 两浮点数相除,结果 double 浮点数
    • 整数和实数相除,自动类型转换为实型
    • 不允许 除 0(与数学一样)
  3. 取模(取余)
    • 运算数必须是整型
    • 对负数取余,结果为余数的绝对值
    • 不允许 除 0(与数学一样)
// 目标: 掌握算术运算符使用特性
int main(void)
{
	// 先乘除后加减
	printf("%d\n", 4 + 6 % 5);	// 5

	// 两整数相除,结果整数(舍小数部分)
	printf("%d\n", 19 / 10);	// 1

	// 两浮点数相除,结果 double 浮点数, 默认保留 6 位小数
	printf("%lf\n", 3.6 / 1.3);	// 2.769231

	// 整数和实数相除,自动类型转换为实型
	printf("%lf, %llu\n", 6 / 2.0, sizeof(6/2.0));  // 表达式结果占 8 字节, double 类型.

	// 除 0 不允许
	printf("%d\n", 6 / 0);  // 被零除或对零取余 错误.

	// 取余运算,参与运算的操作数,必须为整数
	printf("%d\n", 7.3 % 2);	// 表达式必须包含整数 错误.

	// 对负数取余,结果为余数的绝对值
	printf("%d\n", 7 % -5);		// 2

	// 对 0 取余不允许
	printf("%d\n", 6 % 0);  // 被零除或对零取模 错误.

	return 0;
}

总结

算数运算符有哪些?

  • 先 * / %,后 + -。

/ 运算注意什么?

  • 两整数相除得整数。 运算表达式遵循类型转换规则

% 运算注意什么?

  • 运算数必须是整数。 负数取余结果为正。

2. 比较运算符

基础语法

运算符作用示例结果
<判断 小于4 < 3不成立(假):0
<=判断 小于等于4 <= 3不成立(假):0
>判断 大于4 > 3成立(真):1
>=判断 大于等于4 >= 4成立(真):1
==判断 相等4 == 3不成立(假):0
!=判断 不相等4 != 3成立(真):1

**注意:**判断 “相等”,使用 “==”, 不能使用 “=”(赋值符)

优先级

  1. 整体,比算术运算符 低。
  2. 整体,比赋值运算符 高。
  3. > >= < <= 高于 == !=
// 目标: 掌握 比较运算符语法 和 优先级 
int main(void)
{
	// 成立 1, 不成立 0
	printf("10 > 10: %d\n", 10 > 10);
	printf("10 >= 10: %d\n", 10 >= 10);
    
	int a = 10;
	printf("10 <= a: %d\n", 10 <= a);
	printf("10 < a: %d\n", 10 < a);
	
	printf("a != 10: %d\n", a != 10);
	printf("a == 10: %d\n", a == 10);  // 不要将 == 错写成 = 
	
	// 整体,低于 算术运算符
	printf("a >= 3 + 7: %d\n", a >= 3 + 7);  // 先算 +, 再判断 >=
	printf("7 == 3 + 4: %d\n", 7 == 3 + 4);  // 先算 +, 再判断 =

	// 整体, 高于 赋值运算符
    int b;
	b = 4 > a;				// 先算 4 > a, 再赋值
	printf("b = %d\n", b);
	printf("b = %d\n", b = 7 != a);		 // 先算 7 != a, 再赋值.
    printf("b = %d\n", b = 7 != a + 1);  // 先算 a+1, 再判断 7 != a+1, 再赋值.

	// > >= < <= 高于 == !=
	printf("%d\n", 7 > 5 != 3 <= 4);
	
	return 0;
}	

总结

  • 关系运算的比较结果只有两种:1(成立、真)、0(不成立、假)
  • 计算机中判等,需使用 “==”
  • 优先级,高于赋值,低于算数。 > >= < <= 高于 == !=

3. 赋值运算符

目标:会使用赋值运算符表达式**

包括:基本赋值运算符 和 复合赋值运算符( = 与算数运算符 组合而成)。

作用:给变量赋值。 结合性:自右向左

基础语法

运算符术语示例结果
+=加等于int a=1; a+=2;(等同于a = a+2)a值为 3;
-=减等于int a=5; a-=3;(等同于a = a-3)a值为 2;
*=乘等于int a=2; a*=2;(等同于a = a*2)a值为 4;
/=除等于int a=4; a/=2;(等同于a = a/2)a值为 2;
%=模等于int a=3; a%=2;(等同于a = a%2)a值为 1;

**注意:**赋值运算符,会修改变量的原始值。 赋值符左侧,必须可修改(变量)。

int main(void)
{
	// = 赋值符, 自右向左
	int a = 2, b = 1, c = 0;
    
	a = a + b;
	printf("a = %d\n", a);		
	b = a < c;
	printf("b = %d\n", b);  // 直接 打印 b = a < c
	a = b = c = 8;
	printf("a = %d, b = %d, c = %d\n", a, b, c);

	// += -= 复合赋值符。需求:微信钱包有 15.8 元, 发 2.9 元红包,收 13.6 元红包。
	double money;
    money = 15.8;
	money += 2.9;		// 等价于: money = money + 2.9;
	printf("money = %lf\n", money);
	
	// 需求: 发红包
	money -= 13.6;		// 等价于: money = money - 13.6;
	printf("money = %lf\n", money);

    // 其他 复合赋值符。
	int i, j;
    i = 10, j = 5;
	//i *= j;	// 等价于:i = i * j;
	//i /= j;	// 等价与:i = i / j;
	//i %= j;	// 等价与:i = i % j;
	printf("i = %d\n", i);

	// 思考:
	i %= j - 2;			// 等价于 i = i % (j - 2);  %= 右侧看做一个整体.
	printf("i = %d\n", i);
    
    // 注意:赋值符,左侧必须可修改
    3 += 2;

	return 0;
}

总结

  • 先运算,后赋值。方向,自右向左
  • += 可实现累加,将别人的数据累加给自己。
  • 所有赋值运算符,都会修改变量原始值。

4. 自增减运算符

目标:实现数据的增 1、减1运算

自增自减运算也叫 增 1 减 1 运算,都是单目运算。

作用:

  • 自增 ++, 放在变量前面或后面,对变量自身值+1。
  • 自减 --, 放在变量前面或后面,对变量自身值-1。
  • 方便实现变量的 +1 或 -1 运算。

应用场景:

  • 点赞 和 取消点赞。
运算符术语示例结果
++自增int a=1; a++ 或 ++a;(等同于a = a+1)a 值为 2;
自减int b=5; b-- 或 --b;(等同于b = b-1)b 值为 4;

自增自减语法

++ 对变量值 +1。 – 对变量值 -1。

// 目标: 掌握 ++ 自增1, -- 自减1 特性
int main(void)
{
	int a = 10;

	//a++; // a = a + 1;
	++a; // a = a + 1;		与 a++ 效果相同

	printf("a = %d\n", a);
	//a--; // a = a -1;
	--a; // a = a -1;		与 a-- 效果相同

	printf("a = %d\n", a);

	return 0;
}

前缀后缀区别

注意:++ 和 – 如果 不是单独使用(如:用在表达式中),前缀和后缀 差异巨大

  • 放在变量前,先 +1、-1 再取值使用。

    int a = 10;
    int res = ++a;  // 先 +1,再取 a 值给 res。 (先加再用)
    
  • 放在变量后,先 取值用,再 +1、-1

    int b = 10;
    int res2 = b--; // 先取 b 值给 res2, 而后 b 再 -1  (先用再减)
    

代码验证:

// 目标: 掌握 ++/-- 前缀后缀差异
int main(void)
{
	int a = 10;
	int res = ++a;	// 先+1,再用
	printf("res = %d\n", res);

	int b = 10;
	//printf("b = %d\n", b--);	// 先用,再-1
	printf("b = %d\n", --b);	// 先-1,再用
	printf("b = %d\n", b);		// 查看b值

	return 0;
}

注意事项

  1. 不能用于常量
  2. 不能用于表达式
  3. 优先级:整体高于算数运算符(必然高于比较、赋值);后缀高于前缀
  4. 不要在一个表达式中,对同一变量 多次 ++、-- 运算。可读性差,且不用编译系统结果不同。
// 目标: 掌握 ++/-- 使用注意事项
int main(void)
{
	// 1. 不能用于常量
	//printf("%d\n", 10++);

	// 2. 不能用于表达式
	int a = 10;
	// (a - 1)++;
	// ++(-a);

	// 3. 全部 高于算数运算
	//int b = ++a * 3;
	int b = a-- * 3;
	printf("b = %d\n", b);

	// 3. 后缀高于前缀
	printf("a = %d\n", -a++);  

	// 对同一变量 多次 ++、-- 运算。可读性差,且不同编译系统结果不同。
	int i = 10;
	int j = 5;

	int res = i++ + ++i - --j - ++j + 3 + i--;
	printf("res = %d\n", res);	// 26  --- Linux下gcc编译器: 28
	printf("i = %d\n", i);		// 11
	printf("j = %d\n", j);		// 5

	return 0;
}

总结

  • ++ 自增 1, --自减 1
  • 单独使用,前缀后缀没区别;
  • 非单独使用:前缀,先+1、-1,再用; 后缀,先用,再+1、-1
  • 只适用变量,不能用于常量、表达式。
  • 优先级,高于算数、比较、赋值。后缀高于前缀。

5. 逻辑运算符

作用:

  • 用程序解决 类似 或者、并且 这种 含有逻辑关系的 情况。

应用场景:

  • 去京东买手机。 筛选条件: 128G 并且 120w 快充 。 后台 怎么做? 用 与 运算判断,满足展示,不满足不展示。如果用户 就想买 华为 或者 小米手机,后台用 或 运算,筛选厂商对应的手机。

基础语法

  • 将多个条件放在一起运算,最终返回 真(1)或 假(0)
运算符术语示例结果速记
&&2>1 && 3>2&&两边同为真,结果为真,否则为假。同真为真
||2>1||3 > 5||两边有一个为真,结果为真,二者同为假,结果为假。有真为真
!! (2>1)取反!表达式为假,加 ! 为真;表达式为真,加 ! 为假。真非为假

案例1 : 需求,手机存储大于 128,手机屏幕尺寸大于等于 6.35**

// 目标: 掌握逻辑运算符语法特性
int main(void)
{
	int storage = 256;		// 手机存储
	double size = 6.3;		// 屏幕尺寸

	// 需求1: 手机存储大于128, 同时 屏幕尺寸大于等于6.7
	printf("%d\n", storage > 128 && size >= 6.7);  // && 同真为真

	// 需求2: 手机存储大于128, 或者 屏幕尺寸大于等于6.7
	printf("%d\n", storage > 128 || size >= 6.7);	// || 有真为真

	// !非,取反的意思
	printf("%d\n", !6);			// 非真为假
	printf("%d\n", !0);			// 非假为真
	printf("%d\n", !(7 < 9));	// 思考结果是什么?  --> 0
    
    //(使用时特殊情况)判断 20 是介于 10 和 30 之间的数
    // 错误写法
	printf("%d\n", 30 > 20 > 10); 	// C 语言不支持,数学中连续判断的语法

	// 正确写法
	printf("%d\n", 30 > 20 && 20 > 10);

	return 0;
}

案例2 : 判断 20 是介于 30 和 10 之间的数。

// 错误写法
printf("%d\n", 30 > 20 > 10); 	// C 语言不支持,数学的这种连续判断的语法

// 正确写法
printf("%d\n", 30 > 20 && 20 > 10);

短路运算

​ 逻辑运算符的特性,导致实际应用中一部分表达式不执行,也能得出整个表达式结果。这一特点经常作为考点出现在计算机二级、期末考试题中。

在程序中:

  • 判断 表达式 a && (b+c) 的结果:
    • 当 a 为假时,不必计算 b+c,可直接得出表达式为假的结论。
  • 判断 表达式 a || (b+c) 的结果:
    • 当 a 为真时,则不必计算 b+c,就能判断出表达式的值为 真。

**概念:逻辑表达式 运算过程中,只运算左边表达式,就能直接得出整个逻辑表达式的结果。—— 短路运算 **

短路运算作用

​ 在代码中利用短路运算,可 避免不必要运算,提高程序执行效率。 比如有如下代码:

int a = 5, b = 28;
int c = (a > 3) || ((b / 7)*4 % 2 != 0)
printf("c = %d\n", c);

​ 现要计算 c 值。= 右侧表达式含有逻辑或 || 运算符,运算特性 有真为真。|| 左边表达式很容易判断为 真,可确定整个表达式结果为 真。 右侧 b 相关的 复杂表达式 不需要计算 。

短路运算特性

左表达式能直接得逻辑表达式结果,右表达式不执行。

**案例 1:**以下代码执行后,a、b、c 的值依次是多少?

// 目标: 掌握运算特性
int main(void)
{
	int a = 1, b = 2, c = 3;
	(a = b + c) || (++b) ;   	
	printf("a=%d, b=%d, c=%d\n", a, b, c);
    
    return 0;
}

​ 简单分析代码。 很可能得出结论: a = 5,b = 3,c = 3

​ 但,实际上这里的 b 并没有完成自增运算,值还是 2。 为什么 有前缀 ++ 自增,b 值还是 2 呢? 因为 短路运算!++b 并未执行。

​ 逻辑 || 运算符,运算特性有真为真。 左侧 a = b+c 赋值表达式很容易得出结果为真。 因此 整个 表达式得出结论为真,右侧 ++b 并不需要执行。 因此,即使是 前缀自增,b 没有执行机会,值依然为 2。

​ 正确输出结果:a = 5,b = 2,c = 3

**案例 2:**分析代码,推测 a, x, y 的值分别是什么?

// 目标: 掌握运算特性
int main(void)
{
	int x = 1, y = 5, a;
	a = --x && ++y;  
	printf("a=%d, x=%d, y=%d\n", a, x, y);  
    
    return 0;
}    

​ 同样是逻辑运算表达式,逻辑与&& 运算符,运算特性 同真为真。 x 初值为 1,前缀 --x 执行 结果为 0,假。依然会触发短路运算特性。右侧 ++y 不执行。

​ 因此,输出结果为:a=0, x=0, y=5

案例 3: 依然上述案例 2代码,将 --x 修改为 x–,输出结果为何?

// 目标: 掌握运算特性
int main(void)
{    
    int x = 1, y = 5, a;
	a = x-- && ++y;  
	printf("a=%d, x=%d, y=%d\n", a, x, y);  
    
    return 0;
}

​ 修改后,x-- 由于是 后缀,因此 先取值 1 为真(而后再-1),所以没有触发 短路运算,继续运算 右侧 ++y,将 y 值自增为 6。 1 && 6 结果为真, a 值为 1。

​ 因此,输出结果为:a=1, x=0, y=6

小知识:合理利用短路运算特性,提高程序执行效率

  • 编写含**&&**表达式时,&& 同真为真,左表达式值为假时,右表达式不计算, 建议将 易假 值放左边
  • 编写含**||**表达式时,|| 有真为真,左表达式值为真时,右表达式不计算。 建议将 易真 值放左边

总结

  • &&:同真为真; ||:有真为真; ! :真非为假
  • 判断一个数在另两个数范围内,用 && 实现
  • 短路特性:运算符左侧表达式可直接得结论,则右侧表达式不执行
  • 利用短路特性:&&,将易假表达式放左侧;||,将易真表达式放左侧

6. 条件运算符

基础语法

语法:表达式1 ?表达式 2:表达式 3

  • 表达式 1 一定起 判别 作用。表达式 2 和 表达式 3 只能有一个执行。
  • 三目运算的结果,必须被使用。

运算规则:

  • 判断 表达式 1 的结果:

    • 为真,整个三目运算的结果为 表达式 2

    • 为假,整个三目运算的结果为 表达式 3

能解决什么问题呢?比如,查询成绩系统中,根据成绩判定是否及格?可以用 三目运算来进行判断。

案例 1:接收学生成绩,判断是否 及格,给出 Y/N 结果。**

// 目标: 掌握 三目运算语法特性
int main(void)
{
	double score;
    
	printf("请输入成绩:");
	scanf("%lf", &score);

	char res = score >= 60 ? 'Y' : 'N'; // 三目运算结果 赋值给 res 变量

	printf("是否及格? %c\n", res);
	return 0;
}

案例 2:找出两个数中的较小值

// 目标: 掌握 三目运算语法特性
int main(void)
{
	int a = 10;
    int b = 20;

	printf("较小值为:%d\n", a < b ? a : b);	// 三目运算结果在 printf 中使用
	return 0;
}

特性和嵌套应用

​ 嵌套条件运算符的写法,在实际编程中较少见,因为代码可读性低。 但,计算机考试中,经常出做考点。

​ 辨别技巧是,当 表达式中 有 2 个以上问号、冒号,一定是发生了 三目运算嵌套。

​ 处理方法是,先将位于右边的 “?” 与它后面最近一个 “:” 配对。因为,条件运算符的结合性,自右向左。

​ 优先级,高于赋值运算符,低于算数、逻辑、比较运算符。

案例 1:

int res = w < x ? x + w : x < y ? x : y   	//  w < x ? x + w :(x < y ? x : y)

​ 将 右侧的 ?与后面的 :配对,x < y ? x : y 看做一组 三目运算表达式,作为另外一组 三目运算的 表达式 3。

案例 2:

int res = a > b ? c > d ? e : f : g		// a > b ? (c > d ? e : f ): g

​ 将 右侧的 ?与后面的 :配对,c > d ? e : f 看做一组 三目运算表达式,作为另外一组 三目运算的 表达式 2。

​ 这种嵌套写法,看其他人写的程序时,能看懂即可。我们不要这样写。

总结

  • 语法规则:

    • 表达式1 ?表达式 2:表达式 3
    • 表达式 1 为真,整个取表达式 2; 为假,整个取表达式 3
    • 结果必须被使用
  • 嵌套三目运算:

    • 出现 两个以上 ?: ,说明有嵌套。
    • 自右向左,找 “?” 与它后面最近一个 “:” 配对
  • 优先级:

    • 高于 赋值运算符,低于 算数、逻辑、比较运算符。

验收案例

练习1:分析程序,执行结束后 a、b、res 的值分别是多少?**

int main(void)
{    
	int a = 3, b = 4, c = 5, d = 6;
    
	int res = a > b ? a++ : c > d ? ++a : b++;
    
	printf("a = %d, b = %d, res = %d\n", a, b, res);
    
    return 0;
}

练习2:使用三目运算符,编写程序实现找出三个数中的最大值。**

// 方法 1:
int main(void)
{
	int a = 11;
	int b = 22;
	int c = 35;
	int ab_max = a > b ? a : b;
	
	int max = c > ab_max ? c : ab_max;

	printf("abc最大值为:%d\n", max);
	return 0;
}

// 方法 2:
int main(void)
{
	int a = 1, b = 2, c = 3;
	
	int max = c > (a > b ? a : b) ? c : a > b ? a : b;

	printf("abc最大值为:%d\n", max);
	return 0;
}

7,逗号运算符

C语言中,逗号也是一种运算符。 用逗号将多个表达式连接起来,组成逗号表达式。一般形式为:

表达式 1,表达式 2,表达式 3,…,表达式 n

如:a+3, b+4, c+5 是一个 逗号表达式。

求解过程是 自左向右 依次求解。 整个逗号表达式的值,为最后一个表达式 n 的值。

逗号运算符的优先级,是所有运算符中最低的。

练习:分析下面代码执行过程。res 值为多少?

int i = 3;
int res = (i++, ++i, i + 5);  
printf("res = %d\n", res);

总结

取整个逗号表达式值的做法,在实际编程中不常用到。 但,计算机考试中,经常出做考点。记住两句话就好了:

  • 整个逗号表达式的值,为最后一个表达式 的值。
  • 逗号运算符优先级最低(比赋值还低)

练习

分析下列程序执行,i 值为多少?

int i, a;
i = (a = 2 * 3, a * 4), a + 6;
printf("%d\n", i);		// i 值为 24。 因为优先级的原因,i存储的不是 整个逗号表达式的值。

8,运算符优先级

运算符名称
[ ]数组下标
()圆括号
-负号
++、–自增、自减
windows:先++优于后++
mac、Linux从左到右依次计算
&取地址运算符
逻辑非
(类型)强制类型转换
sizeof长度运算符
*
/
%取余
+
-
>大于
>=大于等于
<小于
<=小于等于
==等于
!=不等于
&&逻辑与
||逻辑或
? :条件运算符
=赋值运算符
/=除后赋值
*=乘后赋值
%=取余后赋值
+=加后赋值
-=减后赋值
,逗号运算符

案例 1: 分析下面代码执行过程。res 值为多少?

int a = 0;
scanf("%d", &a);
int res = a < -10 || a >= 10, a > -10 && a <= 10;

案例 2: 分析下面代码执行过程。res 值为多少?

int x = 0, y = 1;
int res = x++ != !y;
printf("res = %d\n", res);

案例 3: 分析下面代码执行过程。res 值为多少?

int i = 35, a = 3, b = 5, c = 7;
int res = i % 7 == 0 && (a != b && b != c && c != a)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值