C语言:运算符

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

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

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

解释:整型、浮点型、字符型之间都可以参与混合运算,字符是特殊的数值型(字符参与数值运算使用的是ASCLL码(0~127))

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

隐式转换

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

语法:

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

转换关系:

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

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

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

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

注意:

类型转换不会改变原数据的类型(不会改变原数据在内存的存储)举例:

int a = 10;  // 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

注意:

类型转换不会改变原数据的类型(不会改变原数据在内存的存储

案例:
  • 需求:强制类型转换案例

  • 代码:

     /*************************************************************************
       > File Name:    demo01.c
       > Author:       三道渊
       > Description:  
       > Created Time: 2025年07月10日 星期四 10时41分07秒
      ************************************************************************/
     ​
     #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运算符
序号名称符号序号名称符号
1算术运算符+ - * / % ++ --8指针运算符* &
2关系运算符> < >= <= == !=9字节数运算符sizeof
3逻辑运算符&& || !10下标运算符[]
4位运算符<< >> ~ | ^ &11强制类型转换运算符(type)
5赋值运算符= += -= *= /= %=12分量运算符. ->
6条件运算符?:13其他函数调用运算符()
7逗号运算符,
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语言规定,两个整型相除,其结果仍然为整型。例如:

  • ((a+b) / (c+d)) != (a+b / c+d)
优先级与结合性

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

各种运算符的结合方向

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

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--

结合方向:自右向左

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

先使用,后计算

说明:

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

② 后计算:再让计算数 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

注意:

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

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

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

--5;                           // 非法的 不能用于常量
int i = 0, j = 0; (i+j)++;     // 非法的 不能用于表达式
#define MAX_VAL 1   NAX_VAL++; // 非法的 不能用于常量

赋值运算符

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

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

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

赋值规则

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

  • 浮点型→整型变量:舍弃小数部分。如:int a = 5.5 → 5;

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

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

赋值表达式

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

语法:

变量 = 表达式;

案例:

a = 5;        // 将字面量赋值给变量(字面量就是常量的一种)
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如何表示?

  1. a++或者++a

  2. a+=1

注意:

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

  • 赋值运算符的优先级属于最低(除了逗号运算符以外),一般都是留到最后运算

关系运算符

说明:>,<,>=,<=,==,!=

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

a > b;   // 变量
5 > 6;   // 常量
a+b>c;   // 表达式
  • 关系运算符运算的结果是布尔类型,C语言实际没有布尔类型,我们用整型的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

    C语言链式调用不会编译报错,为什仫不能用链式调用?

     int score1 = 45, score = -65, score3 = 110;
     printf("%d\n",0 <= score1 <= 100);  //预测:0<= 45 <= 100 结果为1
     //实际结果:0 <= score1 返回1, 1 <= 100 返回1,最终结果1,成立
     ​
     printf("%d\n",0 <= score2 <= 100);//预测:0<= -65 <= 100 结果为0
     //实际结果:0 <= score2 返回0, 1 <= 100 返回1,最终结果1,不成立
     ​
     printf("%d\n",0 <= score3 <= 100);//预测:0<= -65 <= 100 结果为0
     //实际结果:0 <= score3 返回0, 1 <= 100 返回1,最终结果1,不成立
    

    链式比较语法没问题,可以通过编译,但是逻辑有问题,所以不能用作条件判断。

  • 浮点型比较需要用差值法:fabs(a-b)<1e-6.使用fabs取绝对值函数,需要引入math.h

在C语言中,浮点型不用==表示

/*****************************************************************
********
  > File Name:   demo02.c
  > Author:       三道渊
  > Description:  
  > Created Time: 2025年07月10日 星期四 16时30分49秒
 
******************************************************************
******/
#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;
}

运行结果:

运行结果和预期结果有出入,不能使用==

总结:

操作正确方式错误方式
浮点数相等比较使用误差范围(fabs(a - b) < eosilona == b
浮点数大小比较直接使用><-
零比较fabs(a) < eosilona == 0.0

逻辑运算符

运算的结果为布尔值,要么为真-非0,要么为假-0

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

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

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

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

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

    案例:

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

当逻辑或运算时,左侧为真,右侧结果不会影响最终结果,右侧根本不会执行。

案例:

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

逗号运算符

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

别称:顺序求值运算符

逗号表达式

语法:

表达式1,表达式2,...表达式n;

求解过程:按从左到右的顺序分别计算各个表达式的值。

案例:

#include <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

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值