欢迎光临散文网 会员登陆 & 注册

P5.运算符

2023-08-26 03:23 作者:创世十鹰  | 我要投稿

运算符介绍:

运算符是一种特殊的符号,用以表示数据的运算、赋值和比较等。 

1) 算术运算符 (+, -, * , / , %) 

2) 赋值运算符 (= += -= ..) 

3) 关系运算符(比较运算符)(比如 > >= < <= == 等等) 

4) 逻辑运算符 (&& 逻辑与 || 逻辑或 ! 逻辑非) 

5) 位运算符 (& 按位与 | 按位或 ^ 按位异或 ~ 按位取反等等) 

6) 三元运算符 ( 表达式 ? 表达1 : 表达2)


算术运算符:

介绍:算术运算符是对数值类型的变量进行运算的,在C程序中使用的非常多。

案例演示:案例演示算术运算符的使用(operator.c)。 

1) +, - , * , / , %, ++, -- , 重点讲解 /、%、++ 

2) 自增:++ 作为独立的语句使用: 前++和后++都完全等价于 i=i+1; 作为表达式使用 前++:++i先自增后赋值 后++:i++先赋值后自增 

3) -- ,+、-、* 是一个道理,完全可以类推。


细节说明:

1) 对于除号“/”,它的整数除和小数除是有区别的:整数之间做除法时,只保留整数 部分而舍弃小数部分。 例如:int x= 10/3 ,结果是 3 

2) 当对一个数取模时,可以等价 a%b=a-a/b*b , 这样我们可以看到 取模的一个本质 运算。 3) 当 自增 当做一个独立语言使用时,不管是 ++i; 还是 i++; 都是一样的,等价 

4) 当 自增 当做一个 表达式使用时 j = ++i 等价 i = i + 1; j = i; 

5) 当 自增 当做一个 表达式使用时 j = i++ 等价 j = i; i = i + 1;

自增,自减课堂练习:

void main() { 

int i1 = 10, i2 = 20; 

int i = i1++;//i =10, i1=11 

printf("i=%d\n",i);// 10 

printf("i1=%d\n", i1);//11 

i = ++i1; 

printf("i=%d\n", i);//12 

printf("i1=%d\n", i1);//12 

i = i2--; 

printf("i=%d\n",i);// 20 

printf("i2=%d\n",i2);//19 

i = --i2; 

printf("i=%d\n", i);//18 

printf("i2=%d\n", i2);//18 

getchar(); 

}

输出结果: 

i= 10 i1= 11  

i= 12 i1= 12 

i= 20 i2= 19 

i= 18 i2= 18

课堂练习2:

1) 假如还有97天放假,问:xx个星期零xx天 

2) 定义一个变量保存华氏温度,华氏温度转换摄氏温度的公式为:5/9*(华氏 温度-100),请求出华氏温度对应的摄氏温度。


我的源码:

/*

练习要求:

1.假如还有99天放假,问:还有xx个星期零xx天

2.定义一个变量保存华氏温度,华氏温度转摄氏温度的公式:5/9 * (华氏温度-100),请求出华氏温度对应的摄氏温度。

*/

#include <stdio.h>

void main(){

//1思路:

//1.定义一个变量 days 保存天数

//2.定义一个变量 week 保存计算得到的星期

//3.定义一个变量 leftDays 保存剩余天数

//4.要使用 % 和 / 来计算


short days = 99;

short week = days / 7;

short leftDays = days % 7;


//2思路略过

double huaShi = 13;

double sheShi = 5.0 / 9 * (huaShi - 100);// 5.0/9,不然输出都是0(5/9等于0)


printf("还有%d个星期零%d天放假\n",week,leftDays);

printf("华氏温度%.3f转为摄氏温度是%.3f\n",huaShi,sheShi);

getchar();

}


关系运算符(比较运算符) 

介绍:

1) 关系运算符的结果 要么是真(非0 表示),要么是 假(0 表示) 

2) 关系表达式 经常用在 if结构的条件中或循环结构的条件中

细节说明:

1) 关系运算符的结果要么是真(非0 表示, 默认使用1),要么是 假(0 表示)  

2) 关系运算符组成的表达式,我们称为关系表达式。 a > b  

3) 比较运算符 "=="(关系运算符) 不能误写成 "=" (赋值)


我的源码:

/*

关系运算符 也叫 比较运算符

1.关系运算符的结果 要么是真(非0表示,默认使用1表示),要么是假(用0表示)

2.关系运算符组成的表达式,我们称为关系表达式。如 a > b

3.比较运算符 ==(关系运算符) 不能写成 =(赋值)

*/

#include <stdio.h>

void main(){

int a = 13;

int b = 3;


printf("关系表达式 a>b 的值是%d\n",a > b);//1

printf("关系表达式 a>=b 的值是%d\n",a >= b);//1

printf("关系表达式 a<b 的值是%d\n",a < b);//0

printf("关系表达式 a<=b 的值是%d\n",a <= b);//0

printf("关系表达式 a==b 的值是%d\n",a == b);//0

printf("关系表达式 a!=b 的值是%d\n",a != b);//1


getchar();

}


逻辑运算符:

介绍:用于连接多个条件(一般来讲就是关系表达式),最终的结果要么是真(非0  表示),要么是 假(0 表示) 。

练习题2:请写输出结果 

void main() { 

int x=1; 

int y=0; 

short z=42; 

if((z++==42)&&(y=1)) { // z = 43 , y =1 

z++; // z = 44 

    } 

if((x=0) || (++z==45)) { // z = 45 

z++; // z = 46 

    } 

printf("z=%d", z); // z 为46 

getchar(); 

} 结果为:z 为 46

我的源码:

/*

逻辑运算符 (&& || !三个)

用于连接多个条件(一般来讲就是关系表达式),最终结果要么是真(非0表示),要么是假(0表示)

*/

#include <stdio.h>

void main(){

//int a = 10,b=99;

//if(a<20 && b++>100){

// printf("OK100");//不会输出

//}

//printf("b=%d\n",b);//输出b=100


//int a = 10,b=99;

//if(a<2 && ++b>99){

// printf("OK100\n");//也不会输出

//}

//printf("b=%d\n",b);//输出b=99


//1.在就行 && 操作时,如果第一个条件为false,则后面的条件不再判断,整个结果为false

//2.该现象称为 短路现象,所以逻辑与 也称为 短路逻辑与


//int a = 10,b=99;

//if(a<5 || b++>100){

// printf("@@@OK100@@@\n");//不会输出

//}

//printf("b=%d\n",b);//输出b=100


//int a = 10,b=99;

//if(a>5 || b++>100){

// printf("@@@OK100@@@\n");//输出@@@OK100@@@

//}

//printf("b=%d\n",b);//输出b=99


//1.在就行 || 操作时,如果第一个条件为true,则后面的条件不再判断,整个结果为真

//2.该现象称为 短路现象,所以逻辑或 也称为 短路逻辑或


//逻辑非

int score = 100;

int res = score < 99;//res=0

if(res){

printf("Hello Tom\n");

}


if(!res){

printf("Hello Jack\n");

}

getchar();

}


#include <stdio.h>

void main(){

int x=1;

int y=0;

short z=42;

//下面if语句的 赋值语句写在前面不需要括号,写在后面需要括号。优先级问题

if(z++==42 && (y=1)){//z=43,y=1

z++;//z=44

}


if(x=0 || ++z==45){//x=0为假,z=45

z++;//z=46

}

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

getchar();

}


赋值运算符:

介绍:赋值运算符就是将 某个运算后的值, 赋给指定的变量。 赋值运算符一览表 先讲 =、+=、-=、 *= 、/=、%= 

<<=、>>=、&=、^=、 |= 和位运算相关,放 在后面讲解


运算符         描述         实例 

= 简单的赋值运算符,把右边操作数的值赋给左边操作数 C = A + B 将把 A + B 的值赋给 

+= 加且赋值运算符,把右边操作数加上左边操作数的结果赋值给左 边操作数 C += A 相当于 C = C + A 

-= 减且赋值运算符,把左边操作数减去右边操作数的结果赋值给左 边操作数 C -= A 相当于 C = C - A 

*= 乘且赋值运算符,把右边操作数乘以左边操作数的结果赋值给左 边操作数 C *= A 相当于 C = C * A /= 除且赋值运算符,把左边操作数除以右边操作数的结果赋值给左 边操作数

/= A 相当于 C = C / A %= 求模且赋值运算符,求两个操作数的模赋值给左边操作数 C %= A 相当于 C = C % A 

<<= 左移且赋值运算符 C <<= 2 等同于 C = C << 2 

>>= 右移且赋值运算符 C >>= 2 等同于 C = C >> 2 

&= 按位与且赋值运算符 C &= 2 等同于 C = C & 2 

^= 按位异或且赋值运算符 C ^= 2 等同于 C = C ^ 2 

|= 按位或且赋值运算符 C |= 2 等同于 C = C | 2

案例演示:

案例演示赋值运算符的基本使用。 

1) 赋值基本案例 [int num1 = 10 + 3] 

2) 有两个变量,a和b,要求将其进行交换,最终打印结果 

3) += 的使用案例 

赋值运算符特点:

(1) 运算顺序从右往左 

(2) 赋值运算符的左边 只能是变量,右边 可以是变量、表达式、常量值 

(3) 复合赋值运算符等价于下面的效果 比如:a+=3;等价于a=a+3;

我的源码:

/*

赋值运算符:

就是将某个运算后的值,赋给指定的变量

有:= +=... <<=...

简单略过,

<<= 左移且赋值运算符 (c<<=2 等同于 c=c << 2)

>>= 右移且赋值运算符

&= 按位与且赋值运算符

^= 按位异或且赋值运算符

|= 按位或且赋值运算符(c |=2 等同于 c = c | 2)

*/


/*

运算顺序 从右往左

赋值运算符 左边只能是变量,右边可以是变量,表达式,常量值

注意:在运算时,可能截断小数点后面的部分

*/


#include <stdio.h>

void main(){

//int a1 = 10;

//int b1 = 11.1;

//a1+=1.7;

//printf("a1=%d b1=%d\n",a1,b1);//a1=11 b1=11


//有两个变量,a和b,要求进行交换,打印结果

int a = 13;

int b = 1313;

int temp = a;

a = b;

b = temp;

printf("a=%d b=%d\n",a,b);//a=1313 b=13

getchar();

}

位运算符

介绍:位运算符作用于位, 并逐位执行操作。 位运算符一览表 要彻底搞懂位运算, 需要先学习二进制, 因此位运算,我们 放在二进制后讲解


运算符         描述         实例 

& 按位与操作,按二进制位进行"与"运算。运算规则: 0&0=0; 0&1=0; 1&0=0; 1&1=1

(A & B) 将得到 12,即为 0000 1100 

| 按位或运算符,按二进制位进行"或"运算。运算规则: 0|0=0; 0|1=1; 1|0=1; 1|1=1

(A | B) 将得到 61,即为 0011 1101 

^ 异或运算符,按二进制位进行"异或"运算。运算规则: 0^0=0; 0^1=1; 1^0=1; 1^1=0

(A ^ B) 将得到 49,即为 0011 0001 

~ 取反运算符,按二进制位进行"取反"运算。运算规则: ~1=0; ~0=1

(~A ) 将得到 -61,即为 1100 0011一个有符号二进制数的补码形式。 

<< 二进制左移运算符。将一个运算对象的各二进制位 全部左移若干位(左边的二进制位丢弃,右边补0)。 A << 2 将得到 240,即为 1111 0000 

>> 二进制右移运算符。将一个数的各二进制位全部右 移若干位,正数左补0,负数左补1,右边丢弃。 A >> 2 将得到 15,即为 0000 1111

我的源码:

/*

进制介绍

1.二进制:0,1,满2进1,C语言中没有二进制常数的表示方法。

2.十进制:0~9,满10进1。

3.八进制:0~7,满8进1。以数字0开头。

4.十六进制:0~9和A~F,满16进1。以0x或0X开头表示。此处A~F不区分大小写。【A->10,b->11,...f->15】

--0x13bF + 1 ==0x13C0

*/


/*

进制转换:

其他进制转为十进制:0x1dcf==>1*16^3 + d*16^2 + c*16 + f = 7631。其他一样,位数 * 位权


十进制转为其它进制:用短除法,比如十进制->十六进制【一直除以16,直到商为0,再把余数倒过来写】


二进制转为8、16进制:3位二进制对应1wei八进制,4位二进制对应1位十六进制【把它算出来,位*位权 对应 写成一个数】

11 100 101-->八进制--> 3 4 5

11 1001 0110-->十六进制--> 3 9 6


八、十六进制转为二进制:和二进制转为8、16进制类似,反过来看就行

01230-->二进制-->001 010 011 000

0xAB29-->二进制-->1010 1011 0010 1001

*/


/*

【原码、反码、补码】

1.二进制的最高位是符号位,0表示正数,1表示负数

2.正数的原码、反码、补码都一样(三码合一)

3.负数的反码 = 它的原码符号位不变,其它位全部取反(0-->1,1-->0)

4.负数的补码 = 它的反码 + 1

5.0的反码,补码都是0

6.在计算机运算的时候,【都是以补码的方式来运算的】。但是最终结果显示,需要把补码转为原码

*/


/*

【位运算当然和逻辑运算符 不一样】

按位与(&),规则:两边都为1,才为1【0&0=0,1&1=1,0&1=0,1&0=0】

按位或(|),规则:两边有1为1【0|0=0,1|1=1,0|1=1,1|0=1】

按位异或(^),规则:两边相同为0,不同为1【0^0=0,1^1=0,0^1=1,1^0=1】

按位取反(~),规则:两边取反【~1=0,~0=1】


【最终显示是原码,补码最终都要转为原码】【一句话补码计算,原码最终显示】

/*


/*

位运算例子:【int有4个字节,下面是一个字节的【懒得补完整】,算出结果都一样】

~2 = -3;//二进制为 0000 0010 -->反码 0000 0010 -->补码 0000 0010 --》对补码取反 1111 1101--》还原为原码 1000 0011--》-3

~-2 = 1;//二进制为 1000 0010 -->反码 1111 1101-->补码 1111 1110--》对补码取反 0000 0001--》还原为原码 0000 0001--》1

~-5 = 4;//二进制为 1000 0101 -->反码 1111 1010-->补码 1111 1011--》对补码取反 0000 0100--》还原为原码 0000 0100--》4


2 & -3 = 0;//2的二进制为 0000 0010(补码一样)。-3的二进制为 1000 0011(补码 1111 1101)--> 0000 0010 & 1111 1101 =》0000 0000-->还原为原码 0

2 | 3 = 3;//2的二进制为 0000 0010(补码一样)。3的二进制为 0000 0011(补码一样)--> 0000 0010 | 0000 0011 =》0000 0011-->还原为原码(正数原码一样)--》3

2 ^ 3 = 1;//2的二进制为 0000 0010(补码一样)。3的二进制为 0000 0011(补码一样)--> 0000 0010 ^ 0000 0011 =》0000 0001-->还原为原码(正数原码一样)--》1


*/


/*

二进制左移(<<),规则:将二进制全部左移若干位【右边补0,左边二进制位丢弃】

二进制右移(>>),规则:将二进制全部右移若干位【(正数左边补0,负数左边补1),右边丢弃】(补0和1 是因为,不能改变数的符号)


【位运算说明2】

<< 叫算术左移。规则:符号位不变,低位补0

>> 叫算术右移。规则:低位溢出,符号位不变,并用符号位 补溢出的高位。


*/


/*

例子2://照样4个字节,只写其中的1个字节

1 >> 3  // (正数相当于除以3个2-->1/2/2=0)【左移就是乘3个2,2是权重,但是负数不能这样算,因为负数补码和原码不一样】

int a = 1 >> 2;//1的补码 0000 0001-->右移2位--> 0000 0000--》0

int b = -1 >> 2;//-1的补码 1111 1111-->右移2位-->1111 1111-->原码 1000 0001--》-1

int c = 1 << 3;// 0000 0001-->左移3位--> 0000 1000--》8【相当于1*2*2*2=8】

int d = -3 << 3;//-3补码1111 1101--左移3位-->1110 1000-->原码 1001 1000 --》-24


~6;

~-7;

13 & 7;

5 | 4;

-3 ^ 3;

*/


//1000 0000 0000 0001

//反码:1111 1111 1111 1110

//补码:1111 1111 1111 1111



#include <stdio.h>

int main(){

//int num = 011;

//int num2 = 0X13bf + 1;

//printf("num=%d num2=%d",num,num2);//num=9 num2=5056


int num1 = ~2;//-3

int num2 = ~-2;//1

int num3 = ~-5;//4


int num4 = 2 & -3;//0

int num5 = 2 | 3;//3

int num6 = 2 ^ 3;//1


int a = 1 >> 2;//0

int b = -1 >> 2;//-1

int c = 1 << 3;//8

int d = -3 << 3;//-24


printf("num1=%d num2=%d num3=%d num4=%d num5=%d num6=%d\n",num1,num2,num3,num4,num5,num6);


printf("a=%d b=%d c=%d d=%d",a,b,c,d);

getchar();

}


三元运算符

基本语法:条件表达式 ? 表达式1: 表达式2; 

1) 如果条件表达式为非0 (真),运算后的结果是表达式1; 

2) 如果条件表达式为0 (假),运算后的结果是表达式2; 

3) 口诀: 一灯大师 =》 一真大师 


使用细节:

1) 表达式1和表达式2要为可以赋给接收变量的类型(或可以自动转换), 否则 会有精度损失 

2) 三元运算符可以转成if--else 语句 

int res = a > b ? a++ : --b; // if ... else .. 

课堂练习:

案例1:实现两个数的最大值 (a , b ) 

int a = 10; 

int b = 99; 

int res = a > b ? a++ : b--;

案例2:实现三个数的最大值 

int a = 10; 

int b = 100; 

int c = 199; 

int max = a > b ? a : b

运算符优先级 

运算符优先级小结: 

1) 结合的方向只有三个是从右向左,其余都是从左向右 

2) 所有的双目运算符中只有赋值运算符的结合方向是从右向左 

3) 另外两个从右向左的结合运算符,一个是单目运算,还有一个是三目运算() 

4) 逗号的运算符优先级最低 

5) 说一下优先级的大概的顺序 算术运算符 > 关系运算符 > 逻辑运算符(逻辑 非! 除外) > 赋值运算符 > 逗号运算符 

6) 注意不需要刻意的记, 常用就慢慢有印象


优先级问题     表达式     经常误认为的结果     实际结果 (红色标注)

. 的优先级高于 *(-> 操作符 用于消除这个问题)   *p.f     p 所指对象的字段 f,等价于: (*p).f     对 p 取 f 偏移,作为指针, 然后进行解除引用操作,等 价于: *(p.f) 

[] 高于 *     int *ap[]     ap 是个指向 int 数组的指针, 等价于: int (*ap)[]     ap 是个元素为 组,等价于: int *(ap []) 

函数 () 高于 *     int *fp()     fp 是个函数指针,所指函数 返回 int,等价于: int (*fp)()     fp 是个函数,返回 价于: int* ( fp() ) 

== 和 != 高于位操作     (val & mask != 0)     (val &mask) != 0     val & (mask != 0) 

== 和 != 高于赋值符     c = getchar() != EOF     (c = getchar()) != EOF     c = (getchar() != EOF) 

算术运算符高于位移运算符     msb << 4 + lsb      (msb << 4) + lsb     msb << (4 + lsb) 

逗号运算符在所有运算符中 优先级最低     i = 1, 2      i = (1,2)      (i = 1), 2


运算符优先级注 意事项和细节: 

上表中,优先级同 为1 的几种运算符 如果同时出现,那 怎么确定表达式的 优先级呢?这里我 们专门说明一把


我的源码:

/*

位运算后面讲

三元运算符,基本语法:

1.如果 条件表达式 为非0(真),运算后的结果是 表达式1

2.如果 条件表达式 为0(假),运算后的结果是 表达式2

*/


/*

细节:

1.表达式1和表达式2 要为 可以赋给接收变量的类型(或可以自动转换),否则会有精度损失

2.三元运算符可以转换为 if-else语句

*/


#include <stdio.h>

void main(){

//int a = 13;

//int b = 1313;

//int c = 131313;

//int max = a > b ? a : b;

//int max2 = (a>b?a:b)>c?(a>b?a:b):c;//建议使用中间变量max写,简短一点

//

//printf("两个数的最大值是 %d\n",max);//1313

//

//printf("三个数的最大值是 %d\n",max2);//131313


int a =13;

int b = 1313;

int res = a > b ? a++ : b--;

int n1 = a > b? 1.1 : 1.2;//警告:从“double”转换到“int”,可能丢失数据

printf("\na=%d b=%d res=%d",a,b,res);//a=13 b=1312 res=1313

getchar();

}


/*

运算符优先级 (不知道的就查表)

运算符优先级小结

1.结合方向只有3个从右向左,其余都是从左往右

2.所有双目运算符(就是两个操作数那种 + - * /...),只有赋值运算符是 从右向左

3.另外两个 从右向左的运算符,一个是单目运算,还有一个是三目运算

4.逗号的运算符优先级最低

5.大概顺序:算数运算符 > 关系运算符 > 逻辑运算符(逻辑非(!) 除外) > 赋值运算符 > 逗号运算符

---同1级别优先级时:. 高于 *(指针取值的*),[] 高于 *,函数() 高于 *,==和!=高于位操作、也高于赋值符,算术运算符 高于 位移运算符,逗号在所有运算符优先级最低

6.不需要刻意背,多用就有印象了

*/


P5.运算符的评论 (共 条)

分享到微博请遵守国家法律