#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
//研究操作符玩法
int main()
{
//注意,计算机都是对补码操作的
//移位操作符
//<< 左移操作符
//>> 右移操作符
左移
//移位规则:左边抛弃、右边补0
//int a = 10;
//int b = a << 1;
//printf("%d %d", a, b);//在这里想一下a会不会变;a不变呢
要想a变
//a = a << 1;//这样就会改变
//printf("\n%d ", a);
右移
//printf("右移动\n");
右移非为逻辑和算术右移,逻辑太粗暴直接跟左移相反会改变符号位
所以我们一般都是用左边用原有值的符号位填充,右边丢弃的算术右移
注意不能移动负数位
//int num = -1;
//int n = num >> 1;
//printf("\n%d %d", num, n);
//
//& //按位与
// | //按位或
// ^ //按位异或
// 注:他们的操作数必须是整数
//int q = 5;
//int w = -6;
//int e = q & w;//按位与-对应的二进制位,有0则为零,俩1才为1;
//就相当&的运算符,真假为假,假真为假,真真为真
/*printf("\n%d ", e);*/
//按位或与按位与相反在这里不多解释了
/*int r = 6;
int t = 7;
int y = r | t;
printf("\n%d ", y);*/
//按位异或,对应的二进制位上相同则为0,相异则为1
/*int r = 6;
int t = 7;
int y = r ^ t;
printf("\n%d ", y);*/
//运用
//int a = 21;
//int b = a & 1;//这样作用就是可以查出a的补码的最后一位
//printf("%d", b);
//如果你想查倒数第五位
//就可以先左移动到最后一位然后按位与1;因为&1只是求最后一位,所以你要想办法把要查的移动到最后的位置
/*int a = 21;
int b = (a>>4) & 1;
printf("%d", b);
return 0;*/
//变态的面试题
//不能创建临时变量(第三个变量),实现俩个数的交换。
//第一种写法,虽然有缺陷(数据很大时候会出错)
/*int a = 10;
int b = 20;
printf("%d %d \n", a, b);
a = a + b;
b = a - b;
a = a - b;
printf("%d %d \n", a, b);*/
//第二种运用异或的特点来解决
//a^a=0;a^0=a;
//3^3^5=5; *** 3^5^3=5;所以是可以交换的,满足交换律
//int a = 10;
//int b = 20;
//printf("%d %d \n", a, b);
//a = a ^ b;
//b = a ^ b;//重要理解这个 b=a^b;代入第一条式子得到,b=a^b^b;相当于5^3^3=5;
//a = a ^ b;//同理
/*printf("%d %d \n", a, b); */
//操作符局限性,只能作用于整数
//可读性差
//编写代码实现:求一个整数存储在内存中的二进制中1的个数
//第一个法子,分别磨2然后除2;循环直到0;但这个只能求整数的,负数不成立
//第二种是用按位与 &
// 第三种 按位与下一位
//int a = 0;
//scanf("%d", &a);
//int count = 0;
//for (int i = 0; i < 32; i++)//int为32位
//{
// if (((a >> i) & 1) == 1)
// {
// count++;
// }
//}
//printf("%d ", count);
//int a = 0;
//scanf("%d", &a);
//int count = 0;
//while(a)
//{
// a = a & (a - 1);//每次都会去掉补码最右的1;
// count++;
//
//}
//printf("%d ", count);
//
//实现输入一个数判断是否符合2^n
//2^n这个数的二进制中只一个1;
//int a = 0;
//scanf("%d", &a);
//if ((a & (a - 1)) == 0)//vs2022牛逼的一个玩法。alt+回车会给你提示正确的方案
//{
// printf("yes");
//}
//else
// printf("no");
//int a = 0;
//int n = ~a;//按位取反
//printf("%d", n);
//或的玩法,实现在一个数的补码里面任意位置插入1
int a = 13;
//00000000000000000000000001101
//00000000000000000000000010000
//1<<4
a = a | (1 << 4);
printf("a=%d", a);
//在去掉1
a = a & ~ (1 << 4);
printf("\na=%d", a);
return 0;
}
续上节
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
//操作符习题
//int main()
//{
//
//
// //int i = 1;
// //int ret = (++i) + (++i) + (++i);//进行完三次自加,得到i=4;然后再相加4*12
// //printf("ret = %d\n", ret);
//
//
//
// return 0;
//}
//2.
//算术转换
//int i;//这题疑惑,i没初始化,会是多少呢;然后sizeof(i)这个得到多少呢
第一次见认为i=0;然后i--;i变为-1;sizeof(-1)=1;
//int main()
//{
// i--;
// if (i > sizeof(i))//在这里i是int类型,而sizeof计算的是unsigned int
// //所以在这里int要进行算术转换(目前理解,也就是要把i看成补码的形式来比较哦)
// //而-1的补码全是1且无符号,符号位也当作数值来看。因此肯定大于4
// {
// printf(">\n");
// }
// else
// {
// printf("<\n");
// }
// return 0;
//}
//延伸一下,想想char这些类型怎么办
//补充知识点
//整型提升
//为了获得这个精度,表达式中的字符和短整型操作数在使⽤之前被转换为普通整型,这种转换称为整型提升。
//表达式的整型运算要在CPU的相应运算器件内执⾏,CPU内整型运算器(ALU)的操作数的字节⻓度⼀
//般就是int的字节⻓度,同时也是CPU的通⽤寄存器的⻓度。
//因此,即使两个char类型的相加,在CPU执⾏时实际上也要先转换为CPU内整型操作数的标准⻓
//度。
//通⽤CPU(general - purpose CPU)是难以直接实现两个8⽐特字节直接相加运算(虽然机器指令中
//可能有这种字节相加指令)。
//所以,表达式中各种⻓度可能⼩于int⻓度的整型值,都必须先转换为
//int或unsigned int,然后才能送⼊CPU去执⾏运算。
//
// 注意:一个字节八个比特位,int有四个字节
//
// ********
//
负数的整形提升
//char c1 = -1;
//变量c1的⼆进制位(补码)中只有8个⽐特位:
//1111111
//因为 char 为有符号的 char
//所以整形提升的时候,⾼位补充符号位,即为1
//提升之后的结果是:
//11111111111111111111111111111111
//实例1
//char a, b, c;
//
//a = b + c;
//b和c的值被提升为普通整型,然后再执⾏加法运算。
//加法运算完成之后,结果将被截断,然后再存储于a中。
//实战1截断
int main()
{
char a = 5;
//5-int -4个字节 32比特位
//000000000000000000101
//然后char只有一个字节,八个比特位所以取8位出来
//0000101 -a;
//然后进行整型提升
// //如何进⾏整体提升呢?
//1. 有符号整数提升是按照变量的数据类型的符号位来提升的
//2. ⽆符号整数提升,⾼位补0
char b = 127;
//000000000000000000101 a
//000000000000001111111 b
//10000100 c
char c = a + b;
printf("%d", c);//%d打印10进制的有符号的整数,因此在这里c要整型提升
//打印的时候,计算机存的是补码,但我们打印出来的是十进制,
// 我们得把补码转成原码,然后把原码转成十进制数,得到的结果才和打印出来的十进制数一致
c整型提升 取最高位进行补 1111111111111110000100 这个是补码
//所以我们还要转换为原码才能输出 记得符号位不能变
//1111111111111110000100 补
//1000000000000001111011 反 这里是+1
//1000000000000000000100
int q = 1;
float w = 1.5;
int r = q + w;
printf("\n%d", r);
return 0;
}
//char i;
//int main()
//{
// i--;
// if (i > sizeof(i))
// {
// printf(">\n");
// }
// else
// {
// printf("<\n");
// }
// return 0;
//}