c语言负数左移右移_C语言编程(四)

本文详细介绍了C语言中的位运算符,包括左移运算符<<和右移运算符>>,特别是对于负数进行位移操作时的注意事项。还涉及数据类型转换、算术和逻辑运算符、位运算符如按位与、按位或、按位异或及按位取反,并提供了多个实例来加深理解。

知识点1【数据类型转换】

1、自动类型转换

dd945ca41a457ab807143abb4d0b2d74.png

案例:有符号 和无符号的转换

void test02()
{
	int data1 = -20;
	unsigned int data2 = 10;
 //有符号data1和无符号data2参加计算的时候
 //会先将data1转换成无符号(-20的补码很大的正数) 
 //很大的数 + 10 必然 >0
 if(data1+data2 > 0)
 {
 printf(">0n");
 }
 else if(data1+data2<0)
 {
 printf("<0n");
 }
}
运行结果:>0
案例:int double的转换
void test03()
{
	int data1 = 10;
 printf("%dn",sizeof(data1+3.14));//8字节
}
int main(int argc,char *argv[])
{
 test03();
 return 0;
}

案例:char 和short的类型转换

void test04()
{
	char ch = 'a';
	short data = 20;
 
 //由于char short自身字节数 过小 很容易溢出
 //所以 只要char short参加运算 都会将自身转换成int
 printf("%dn", sizeof(ch + ch));//4
 printf("%dn", sizeof(ch + data));//4
 printf("%dn", sizeof(data + data));//4
}
案例:强制类型转换
void test05()
{
	float x = 3.14f;
	int j = 0;
 //强制 类型转换 只是临时的转换 当前语句有效 在后面的语句中不会更改x的值
	j = (int)x;
 printf("j = %d,x = %fn", j, x);//
}
int main(int argc,char *argv[])
{
 test05();
 return 0;

运行结果:

77f4ab63ceaff1fb4b2245d367e0efef.png

知识点2【运算符】

1、算术运算符

a /b (a,b可以为整数,也可以为浮点数 如果a b为整数 表示取整 如果 a b只要有一个为浮点数 则表示除法运算) 取整 %取余 必须为整数

void test06()
{
 printf("%dn", 5/2);//取整 2
 printf("%dn", 5%2);//余数 1
}
int main(int argc,char *argv[])
{
 test06();
 return 0;
}

运行结果:

4b26415a8d3ce5761f6b91cbc4c4a6b4.png

案例:键盘输入一个数 是否能被3整除

void test07()
{
	int num = 0;
 //键盘输入一个int数
 printf("请输入一个整形数据:");
 scanf("%d", &num);


 //判断是否能被3整数
 if(num%3 == 0)
 {
 printf("okn");
 }
 else
 {
 printf("non");
 }
}
int main(int argc,char *argv[])
{
 test07();
 return 0;
}

运行结果:

522cdc79f9c4d7e1f8fa332d70321e20.png

练习:键盘输入一个4位数 请取出每位上的数值

void test08()
{
 printf("%dn", 5/2);//取整
 printf("%fn",5/2.0f);//除
}

运行结果:

5aaea99dc5723f89a7639b485bd2e6be.png

2、逻辑运算符

!逻辑非 !0 == 真 !真 == 假0

void test09()
{
 printf("%dn", !1);//0
 printf("%dn", !0);//1


 //C语言  0为假 其他都为真  -1
 printf("%dn", !-1);//0
}
int main(int argc,char *argv[])
{
 test09();
 return 0;
}

运行结果:

a0eaeb27237e00629f647f9073a36d83.png

逻辑 && (重要)

A && B A B同时为真 整个表达式结果为真。 A B只要有一个为假 整个表达式为假

void test10()
{
 if( (2>3) && (5>4) )
 {
 printf("okn");
 }
 else
 {
 printf("non");
 }
}
int main(int argc,char *argv[])
{
 test10();
 return 0;
}

运行结果:no

逻辑&& 短路特性

A && B 如果A为假 系统不会执行B 这就是&&的短路特性

void test11()
{
	int num=10;
 printf("比较之前num = %dn",num);


 (2>3) && (num=100);
 printf("比较之后num = %dn",num);




}
int main(int argc,char *argv[])
{
 test11();
 return 0;
}

运行结果:

4c16eee95761d25d0d611d7eb89f253c.png

逻辑||

A || B 只要A B任意一个为真 整个表达式结果为真,A B同时为假的时候 结果才为假。

逻辑|| 也有短路特性:只要A为真 编译器不会判断B的真假。

void test12()
{
	int num=10;
 printf("比较之前num = %dn",num);//10


 (3>2) || (num=100);//num=100得不到执行
 printf("比较之后num = %dn",num);//10
}
int main(int argc,char *argv[])
{
 test12();
 return 0;
}

运行结果:

987232e668e0ad12becb31cb118addec.png

综合案例:

177beaa1737ae5da9be91e23ee4f30a8.png

知识点3【位运算符】二进制位操作(重要)

&:按位与

语法:全1为1 其他为0

    1010 1010
&  1111  0000
--------------------
    1010 0000 

特点:和1相与 保持不变 和0相与 清零

应用场景:将固定为清零。

|:按位或

语法:有1就为1 全0才为0

    1010 1010
|   1111  0000
----------------------
    1111  1010

特点:和0相或 保持不变 和1相或 置1.

应用场景:将固定为置1.

案例:将1010 1010的第2、3为置1 其他为保持不变

    1010 1010
|   0000 1100
-------------------
    1010 1110   

~:按位取反

语法:0变1 1变0

~1010 1010 == 0101 0101

应用场景:配合 & | 操作

^:按位异或

语法:相同为0 不同为1

    1010 1010
^   0000 1111
----------------------
    1010  0101

特点:和0异或 保持不变 和1异或 取反。

应用场景:将固定的为 发生高低电频 翻转。

案例:将1010 1010 的第0位 发生翻转.

 1010 1010
^   0000 0001
----------------------
 1010  1011
^   0000 0001
---------------------
 1010 1010

<< 左移运算符: 左边丢弃 右边补0

注意:移动的位数 不要 超过自身长度

1010 1100 << 2

deb45f950907e056bf810efd440a14ae.png

>> 右移运算符:

1010 1100 >> 2

7fde45cd1c5c3f724e3fa950556ccb62.png

右移分类:逻辑右移 算术右移

逻辑右移:右边丢弃 左边补0.

算术右移

无符号数:右边丢弃 左边补0。

有符号数:

正数:右边丢弃 左边补0。

负数:右边丢弃 左边补1。

右移基本上是右边丢弃 左边补0 只有负数且算术右移 左边才会补1.

逻辑右移和算术右移 是编译器决定,但是我们可以检测。

综合案例:将data的第1、5清0, 第3, 4位置1 其他为保持不变

unsigned char data = 0xaa;//1010 1010
将data的第1、5清0:
data = data & 1101 1101;
1101 1101 = ~(0010 0010) =~(0010 0000 | 0000 0010)
0010 0000 = 0000 0001 << 5
0000 0010 = 0000 0001 << 1
1101 1101 = ~(0x01 <<5 | 0x01<<1)
data = data & ~(0x01<<5 | 0x01<<1);
第3, 4位置1:
data = data | 0001 1000;
0001 1000 = 0001 0000 | 0000 1000
 = 0x01<<4 | 0x01<<3
data = data | (0x01<<4 | 0x01<<3);

知识点4【?:】

表达式1 ? 值1:值2

语法:如果表达式1 为真 整个表达式的值为“值1” 否则为“值2”

案例:

void test01()
{
	int ret = 0;
	ret = 3>2? 5:6;


 printf("ret = %dn", ret);//5
}
int main(int argc,char *argv[])
{
 test01();
 return 0;

案例:逗号运算符

void test02()
{
	int data1 = 0;
	int data2 = 0;


	data1 = 3,4,5,6;
	data2 = (3,4,5,6);
 printf("data1 = %dn",data1);//3
 printf("data2 = %dn",data2);//6


}
int main(int argc,char *argv[])
{
 test02();
 return 0;
}

知识点5【复合运算符】

+= -= *= /= %= 等等

a += b; ==> a = a + b;

a *= b; ==> a= a * b;

注意:=号 右边必须看成一个整体

案例:

void test03()
{
	int data = 3;
 //将=右边看成一个整体
	data *= 3+5;//data = data * (3+5);
 printf("data = %dn",data);//24
}
int main(int argc,char *argv[])
{
 test03();
 return 0;
}

知识点6【++ -- 运算符】

++i 或 --i 先加、减 后使用。

i++ 或 i-- 先 使用 后 加、减

案例:

void test04()
{
	int i = 3;
	int j = 0;


 //++左边 先加 后使用
	j = ++i;//i=i+1;  j=i;


 printf("i = %d, j = %dn", i,j);//4  4
}

案例:

void test04()
{
	int i = 3;
	int j = 0;
 
 //先使用  后 加、减
	j = i++;//j=i; i=i+1;


 printf("i = %d, j = %dn", i,j);//4  3
}
int main(int argc,char *argv[])
{
 test04();
 return 0;
}

注意:i++ 或 ++i 作为单独的指令 没有区别

void test05()
{
	int i=3;
	int j=3;
 
	i++;//i=i+1;
 printf("i = %dn",i);//4


 ++j;//j=j+1
 printf("j = %dn",j);//4




}
int main(int argc,char *argv[])
{
 test05();
 return 0;
}

知识点6【优先级】分析已有的代码

优先级 高 先执行, 同级别的优先级 要看结合性。

8e603a8df2c6ec5991211b5fc3f4411a.png

641b8520c2999003ec6136966dcb22d1.png

自己写代码, 尽量加()。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值