C语言:运算符

内容提要

  • 运算符

    • 算术运算符

    • 赋值运算符

    • 关系运算符

    • 逻辑运算符

    • 逗号运算符

    • 位运算

  • 流程控制

    • 算法

    • 程序的三种结构

    • C语句

运算符

各类数值型数据间的混合运算

  • 整型、浮点型、字符型数据可以进行混合运算/如:

     10 - 'a' * 1.5
     =10 - 97 * 1.5   //保证参与运算的都是数字
     =10.0 - 97.0 *1.5  //不同类型的数据类型可以参与运算,编译器会自动将其转换为同一数据类型后在运算(隐式类型转换)   

    解释:整型,浮点型,字符型之间都可以参与混合运算,

    是应为他们都是数值型,字符是特殊的数值型(字符参与数值运算使用的是ASCII码(0~127)

    运算时,参与运算的两个运算数如果类型不同,则首先将其类型转换为一致再运算。转换规则分为隐式转换显示转换

隐式转换

将低等级类型自动提升为高级等级类型,又被称为自动转换类型。是由编译系统再控制类型转换。

语法

 高等级类型 变量名 =低等级类型变量;

转换关系:

①(低等级类型) int → unsigned int → long → double(高等级类型)

注意:int 与unsigned int 的转换顺序可能因为平台(如位数)和编译器不同而有差异,与结合具体环境判断。

②(低等级类型) char/short → int(高等级类型)

③ (低等级类型) float → double(高等级类型)

注意:

在混合运算过程中,系统所进行的类型转换并不会改变原数据的类型(不会改变数据在内存中的存储),只是在运算过程中将其值编程同类型后运算,举例:

int  a = ;            // a 是 int
 double c = a + 22.5;  // 此时 a临时转换为double类型 即 double c = 10.0 + 22.5
 a = 21 ;              // a是 int
 float c2 = a + 21.5f; // 此时 a临时转换为float类型,即 float c2 =21.0f + 21.5f
 a = 10 ;             // a 是 int
显示转换

需要我们手动指定转换类型,又被称作强制类型转换。是程序眼自己来控制转换。

语法:

(type)(表达式)

举例:

  • (double) a :将a 的值转换为double类型。

  • (int)(x+y) :将x+y的结果转换为int类型。

  • (int)x+y:将x的值转换为int后与y参与加法运算。

举例

double a = 2,b = 3;      // a,b都是double类型
 double c = (int)a + b ; //将a转换为int类型,此时为显示转换,混合运算时a转换为double,此时为隐式转换
 ​
 double num1= 12.55 ;    //num1是double类型
 int num2 = (int)num1; //num1原本是double类型,在赋值运算时,显示转换为int类型
 printf("%d\n",num2); //12 注意:小数转整数会舍弃小数部分,保留整数部分
 num1=15;              //此时num1依然是double

注意:类型转换只是发生在程序运行过程中。并不会改变其在内存中的存储形式。在强制类型转换的过程中,并不会改变原变量的类型,只是在运算过程中将其值转换类型后在运算。

案例:

需求:强制类型转换案例

 #include <stdio.h>
 int main(int argc,char *argv[])
 {
 float x;
 int i;
 x = 3.6f; // float类型的变量,如果赋值是同类型常量,常量需要跟上
 F/f
 i = (int)x;// 将x在程序运行阶段,强制转换为int类型
 printf("x=%f,i=%d\n",x,i); // x=3.600000,i=3 浮点型数据转换为整
 型,会丢失小数部分
 return 0;
 }

说明:x仍然为float类型,可见强制类型转换并不会改变变量原本的类型。

C运算符和C表达式

C运算符

C表达式

所谓表达式就是将操作对象用运算符链接起来的符合C语言语法规则的式子。(表达式=运算数+运算符)

序号名称举例
1算术表达式2 + 6.7 * 3.5 计算结果是数值类型
2关系表达式x > 0, y < z + 6 ,计算结果是布尔类型,0-假 和 非0-真
3逻辑表达式x > 0 && y > 0 ,计算结果是布尔类型,0-假 和 非0-真
4赋值表达式a = 5.6, sum += i 规则:由右往左
5逗号表达式x = 3,y+=4,z-=8 分隔,并列,计算结果就是最后一个表达式

C语言规定了运算符的优先级和结合性。在表达式求值时,按运算符的优先级的高低次序

执行。如果运算符对象两侧的运算符优先级相同,如a +b +c,则按照规定的“结合方向”处

理。

C语言运算符的优先级

算数运算符

基本的算数运算符

+,-正负值运算符(单目/一元运算符:只有一个运算数),举例:

+5  //正5
 5   //正5
 -5  //负5

+ ,- ,* ,/,%加减乘除取余运算符(双目/二元运算符:有两个运算数)注意:除法运算中,除数不能为0

这些算数运算符的运算顺序与数学上的运算顺序是相同的。*,/,%的优先级高于+ ,-

表达式和运算符的优先级和结合性
算数表达式

定义:用算数运算符和括号将运算对象链接起来,符合C语言规范的算式,例如:

 a * b / c - 1.5 + 'A'
  • 表达式中各种运算符的运算顺序,必要时需要添加括号,例如:

     ((a+b) / (c+d)) !=(a+b / c+d)
  • 表达式中各种运算对象的数据类型,特别是整型相除,C语言规定,两个整型相处,其结果仍然为整型。例如:

     7/6 值1
     4/7 值0
     1/2 值0
优先级与结合性

定义:在表达式求解的时候,先按运算符的优先级别的高低次序执行。若一个运算对象两侧的运算符的优先级相同,则按规定的结合方向处理。

各种运算符的方向

①算数运算符的结合方向:自左向右,也就是运算对象先于左边的运算符结合,例如:

 a - b + c;  //先计算左边a-b ,然后+c

②特殊运算符的结合方向:自右向左,也就是运算对象与右边的运算符结合,例如:

 i ++

③如一个运算符两侧的数据类型不同,会自动转换为同类型后计算。

 12 + 12.5 + 'A'
 = 12.0 + 12.5 + 'A'
 = 24.5 + 65
 = 24.5 + 65.0
 = 89.5
自增,自减运算符

作用:使变量的值增1或者减1

结合方向自左向右/自右向左

++i ,--i

结合方向自左向右

表示在使用该运算符对象之前,先让运算数i自身增1或者减1,然后再使用它,也就是使用增1或者减1后的值

先计算,后使用

说明:

①先计算:先让计算书i=i+1

②后使用:将计算后的运算数进行赋值,比较等操作

举例:

 int i = 1; // i = 1
 int x = ++i;// ++i可以看做是一个没有名字的新变量,
 // 上面两行代码等价于:
 // int i = 1;
 // i = i + 1;
 // int x = i;
 printf("i=%d,x=%d\n",i,x); // i=2,x=2
 printf("i=%d,x=%d\n",++i,x);// i=3,x=2
 ​
 int a = 1;
 printf("a=%d\n",++a); // a=2
i ++ ,i--

 结合方向自右向左

表示在使用该运算符之后

先使用,后计算

说明:

① 先使用:将计算前的运算数进行赋值、比较等操作

② 后计算:再让计算数 i = i + 1

举例:

 int i = 1; // i = 1
 int x = i++;// i++可以看做是一个没有名字的新变量,
 // 上面两行代码等价于:
 // int i = 1;
 // int x = i;
 // i = i + 1;
 ​
 printf("i=%d,x=%d\n",i,x); // i=2,x=1
 printf("i=%d,x=%d\n",i++,x);// i=2,x=1
 ​
 int a = 1;
 printf("a=%d\n",a++); // a=1

总结:不管是++i还是i++,运算数i自身都增1;同理不管是--i还是i--,运算数自身都减1。它们的不同之处在于赋值给整体(i++或者++i)的顺序

注意:

++--运算符只适用于整型变量或者字符型变量,而不能用其他类型的变量,如:

 int i =0;
 i++;   //i=1,(i++)=0
 ++i;   //i=2,(++i)=2
 ​
 char a='A'; //65
 a++ ;       //a=66 ,(a++)=65

++--运算符不能用于常量或者表达式,如:

 --5 ; //非法的  不能用于常量
 int i=0,j=0;(i+j)++; //非法的,不能用于表达式
 #define MAX_VAL 1 MAX_VAL++ //非法的,不能用于常量
 练习
     // 第1题:
 int i = 1;
 int n = i++ + ++i - --i + i--;
 // 分解步骤:
 // 1. i++ → 1(i=2)
 // 2. ++i → 3(i=3)
 // 3. --i → 2(i=2)
 // 4. i-- → 2(i=1)
 // 结果:1 + 3 - 2 + 2 = 4
 ​
 // 第2题:
 int i = 10;
 int j = 5;
 int k = i++ + ++i - --j - i--;
 // 分解步骤:
 // 1. i++ → 10(i=11)
 // 2. ++i → 12(i=12)
 // 3. --j → 4 (j=4)
 // 4. i-- → 12 (i=11)
 // k = 10 + 12 - 4 - 12 = 6
 ​
 注意:正式的编程中,切记不能有上面的写法,因为这种代码有风险,属于未定义行为(UB)

赋值运算符

=称之为赋值运算符,其作用是将一个数据赋值给一个变量,如:

int a = 5;     //将常量赋值给变量
 int b = a;     //将变量赋值给变量
 int c = a + b; //将表达式赋值给变量

执行赋值运算的结果,是将右边的数据存入到左边变量对应的内存单元,赋值运算的顺序:自右向左

赋值运算

如果赋值运算符两侧的类型不一样,则在赋值时进行类型转换,转换规则:

  • 浮点型→整型变量:舍弃小数部分

  • 整型→浮点型变量:数值不变,以浮点型存储如:double a=5 →5.000000...

  • 字符型→整型变量:放在整型的低八位,保持原值不变规则。如int a = 'A'

赋值表达式

实现赋值运算的表达式,由赋值运算符+运算数构成。

语法:

变量 = 表达式

案例:

a = 5 ; //将一个常量(字面量)赋值给变量a
 y= 2 * x + 3 ; //将表达式赋值给变量
 a = a + 1;   //将表达式赋值给变量

作用:

将右边表达式的值赋值给左边的变量。赋值表达式的取值取自左边变量的值。(赋值表达式的值就是变量的值)

什么是表达式:

表达式=运算数+运算符

什么是运算数:

常量,变量,表达式都是运算数

复合赋值运算符

说明:+=-=*=/=%/,等

左右两侧操作完毕后,赋值给左边的变量,例如:

 int a = 1 ;
 a += 3 ;  //等价于a=a+3
 a -= 3 ;  //等价于a=a-3
 a *= 3 ; //等价于a=a*3
 ... 

a=a+1如何表示?

a++ 或者++a

a+=1

注意

①在运算时:不能将(=)写作(==)

②赋值运算符的优先级属于最低的(除逗号运算符外),一般留着最后运算

关系运算符

说明:> < >= == !=

  • 所有的关系运算符都是双目运算符(二元运算符),运算符的左侧和右侧可以是常量,变量(字面量,符号常量,使用const修饰的变量)、还可以是表达式,举例:

     a > b;  //变量
     5 > 6;  //常量
     a+b>c;  //表达式
  • 关系运算符的结果是bool类型,我们用整型的0和非0来表示成立(真)或者不成立(假)

     int a = 5 , b = 4 ;
     printf("%d,%d\n",a>b, a+b>10)//1,0 真为1,假为0

    C99标准引入stdbool.h,本质是对0和1进行了封装,就是定义了两个符号常量:

     #define true 1
     #define false 0

注意:

  • 避免链式调用(如0 <= score <=100),应该为:score >=0 && score <=100

    例子:

    int score1 = 45, score2 = -65, score3 = 110;
     // 预测:0 <= 45 <= 100 结果为1
     printf("%d\n",0 <= score1 <= 100);//实际结果:0 <= score1 返回1,1<= 100返回1,最终结果1,成立
     ​
     // 预测:0 <= -65 <= 100 结果为0
     printf("%d\n",0 <= score2 <= 100);//实际结果:0 <= score2 返回0,0<= 100返回1,最终结果1,不成立
     ​
     // 预测:0 <= 110 <= 100 结果为0
     printf("%d\n",0 <= score3 <= 100);//实际结果:0 <= score3 返回1,1<= 100返回1,最终结果1,不成立
  • 浮点型比较需要用差值法:fabs(a-b)<1e-6.使用fabs取绝对值函数,需要引入math.h

#include <stdio.h>
 ​
 int main(int argc,char *argv[])
 {
     float a = 1.1f + 1.2f; // a 预测结果:2.3f
     float b = 2.3f; // b 预测结果:2.3f
     
     printf("1.1f + 1.2f = %.20f\n",a); // %.20f 意思是保留小数点后20位
     printf(" 2.3f = %.20f\n",b);
     
     double a1 = 1.1 * 2;
     printf("%d\n",a1 == 2.2);
     
     return 0;
 }

运行结果:

测试发现:跟预期结果有出入,所以不能使用==

总结:

逻辑运算符

运算的结果为bool类型,要么为真-非0,要么为假-0

  • 逻辑非单目运算符,并且只能在操作数的左侧;非真即为假,非假即为真。

    • 对一个数或者表达式区非奇数次,结果与原值相反(如!(a % 2 !)= 0)是一次取非,结果:a % 2 == 0

    • 对一个数或者表达式取非偶数次,结果与原值相同(如:!!(a % 2 == 0))是2次取非,结果:a % 2 == 0

  • &&:与(逻辑与)双目运算符,当左右两侧的数据都为真时,最终的结果才为真(有假则为假

    当逻辑与运算时,左侧为假右侧根本不执行,最终的结果就是左侧的结果(假),这种现象称之为短路效果(短路与),这是C语言提供的一种惰性运算,为了减少运算次数。

    案例:

     //要求成绩在0~100以内
     int score = 90;
     printf("%d\n",score>=0 && score<=100);//1
  • ||:或(逻辑或)双目运算符,当左右两侧都为假时,最终结果才为假(有真则为真)

    当逻辑或运算时,左侧为真,右侧根本不执行, 最终的结果就是左侧的结果(真),这种现象称之为短路效果(短路或),这是C语言提供的一种惰性运算,为了减少运算次数。

     //闰年计算公式
     int year = 2025;
     printf("%d\n",(year % 4==0 && year %100 !=0 || year % 400 == 0));

逗号运算符

作用:将若干个表达式‘’串联起来‘’,如:a = 4, a + =3;

别称:顺序求值运算符

逗号表达式

语法:

 表达式1 , 表达式2,表达式3 ,.....

求解过程:按从左到右的顺序分别计算各个表达式的值,其中最后一个表达式n的值就是整个逗号表达式的值

案例:

#includ <stdio.h>
 ​
 int main ()
 {
     int a = 0 ,b = 0; //这里是逗号分隔符
     
     //逗号表达式
     int result = (a = 3 ,b = 5, a + b); //8 整体是赋值表达式,=右侧是逗号表达式
     
     //结合条件判断
     int  x = 10 , y = 20 ;
     int max = (x++ , y++,(x > y)? x : y); // x=10 ,y=20 ,max=21
     printf("result=%d,max=%d\n",result,max);//result=8,max=21
     
     return 0
 }

位运算

说明:按位(bit)来进行运算操作的运算符,更多时候用于定制应用开发和嵌入式开发。

语法:~、&、|、<<、>>

~:按位取反

说明:单目运算符,数据的每一个bit位按位取反,也就是二进制数据位上,0变1,1变0

演示:

举例:

 printf("%d\n",~5);
&:按位与

说明:双目运算符,对于运算符左右的两个数,对应的二进制位数都为1时。结果为1,否则为0

演示:

举例:

 printf("%d\n",5 & 6); //4
| :按位或

说明,双目运算符,对于运算符左右的两个数据,对应的二进制位数有一个为1,结果为1,否则为0

演示:

举例:

printf("%d\n",5 | 6); //7
^ : 按位异或

说明:双目运算符,对于运算符左右的两个数据,对应的二进制位数据相同,结果为0,否则为1

演示:

举例:

 printf("%d\n",5 ^ 6);  //3

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值