作者:~小明学编程
文章专栏:C语言基础知识
目之所及皆为回忆,心之所向皆为过往
目录
两个int(32位)整数m和n的二进制表达中,有多少个位(bit)不同
移位规则
将其二进制位向左移动移位,然后右边补0
- int main()
- {
- int a = 10; //00000000000000000000000000001010
- int b = a << 1;//00000000000000000000000000010100
- printf("a=%d,b=%d",a, b);
- return 0;
- }
这是我们的移位结果,其作用相当于将a乘以2。

值得我们注意的是虽然我们对a进行了移位操作但是a本身没有变我们可以看到a的值还是10。
具体是左移还是右移要看具体的机器,在我们的VS2022中是用的算数右移。
- int main()
- {
- int a = -10; //1111 1111 1111 1111 1111 1111 1111 0110
- int b = a >> 1;//1111 1111 1111 1111 1111 1111 1111 1011
- printf("a=%d,b=%d", a, b);
- return 0;
- }

这里我们可以看到右移操作相当于除2的功能(当是负数是会在除2的基础上-1)。
& // 按位与| // 按位或^ // 按位异或注:他们的操作数必须是整数。
运算规则:按位于的运算法则就是在两个数的二进制表示中如果有一个是0那么其结果就是0,只有两个对应位全是1,其结果才是1。
运算规则:按位于的运算法则就是在两个数的二进制表示中如果有一个是1那么其结果就是1,只有两个对应位全是0,其结果才是0。
运算规则:按位于的运算法则就是在两个数的二进制表示中如果两个对应位相同则为0,对应位不同则为1。
- int main()
- {
- int a = 1;//00000000000000000000000000000001
- int b = 2;//00000000000000000000000000000010
- int c = 0;
- printf("%d\n", a & b); //00000000000000000000000000000000
- printf("%d\n", a | b); //00000000000000000000000000000011
- printf("%d\n", a ^ b); //00000000000000000000000000000011
- return 0;
- }

- int main()
- {
- int a = 10;//00001010
- int b = 20;//00010100
- printf("交换前:a=%d,b=%d\n", a, b);
- a = a ^ b;// 00011110
- b = a ^ b;// 00001010
- a = a ^ b;// 00010100
- printf("交换后:a=%d,b=%d\n", a, b);
- return 0;
- }

- int main()
- {
- int a = 0;
- int count = 0;
- int flag = 1;
- printf("请输入:");
- scanf("%d", &a);
- while (flag<=32)
- {
- if (((a >> flag) & 1) == 1)
- count++;
- flag++;
- }
- printf("%d的二进制形式中1的个数为%d", a, count);
- return 0;
- }

- int main()
- {
- int a = 0;
- int b = 0;
- int count = 0;
- int flag = 1;
- printf("请输入:");
- scanf("%d %d", &a, &b);
- while (flag <= 32)
- {
- if (((a >> flag) & 1) != ((b >> flag) & 1))
- count++;
- flag++;
- }
- printf("共%d个bit位不同", count);
- return 0;
- }

赋值操作符是一个很棒的操作符,他可以让你得到一个你之前不满意的值。也就是你可以给自己重新赋值。
- int main()
- {
- int weight = 120;//体重
- weight = 89;//不满意就赋值
- double salary = 10000.0;
- salary = 20000.0;
- //赋值操作符可以连续使用,比如:
- int a = 10;
- int x = 0;
- int y = 20; a = x = y+1;//连续赋值
- //这样的代码感觉怎么样?
- //那同样的语义,你看看:
- x = y+1; a = x;
- //这样的写法是不是更加清晰爽朗而且易于调试。
-
- return 0;
- }
int x = 10 ;x = x + 10 ;x += 10 ; // 复合赋值// 其他运算符一样的道理。这样写更加简洁。
- int main()
- {
- int a = -10;
- int* p = NULL;
- printf("%d\n", !2);
- printf("%d\n", !0);
- a = -a;
- p = &a;
- printf("%d\n", sizeof(a));
- printf("%d\n", sizeof(int));
- printf("%d\n", sizeof a);//这样写行不行?
- //printf("%d\n", sizeof int);//这样写行不行?
- return 0;
- }
这里我们可以看到当sizeof后面是类型的时候则必须加上括号。
- int main()
- {
- int a = 10;
- int n = 0;
- scanf("%d", &n);
- //把a的第n位置为1
- a = a | (1 << (n-1));
- printf("a=%d\n", a);
-
- //把a的第n位置为0
- a = a & ~(1 << (n - 1));
- printf("a=%d\n", a);
-
- //00000000000000000000000000001010
- //00000000000000000000000000010000
- //1<<2;
- //00000000000000000000000000011010
- //11111111111111111111111111101111
- //00000000000000000000000000010000
- //00000000000000000000000000001010
- return 0;
- }
这里我们刚好结合着按位与和按位或解决了这个问题。
下面给大家简单介绍一个易错点
- int main()
- {
- short s = 10;
- int a = 2;
- s = a + 5;
-
- printf("%zu\n", sizeof(s = a + 5));
-
- printf("%d\n", s);
- return 0;
- }
上面程序的结果是什么呢?(%zu是输出的无符号整型)

我们可以看到是2 7,s是short所以占两个字节但是s不是+5了吗为什么不是12呢?
因为sizeof()括号里面的表达式我们是不计算的。
- #include
- int main()
- {
- int i = 0,a=0,b=2,c =3,d=4;
- i = a++ && ++b && d++;
- //i = a++||++b||d++;
- printf("a = %d\n b = %d\n c = %d\nd = %d\n", a, b, c, d);
- return 0; }
- //程序输出的结果是什么?

这里为什么只有a变了,其他的为啥没有变化呢,这里是因为当我们a=0通过&&的判断后面无论是真还是假,这个整体的结果都是假,所以后面的自增操作没有进行。
- //代码3 a = get_val();
- count_val(a);
- while (a > 0)
- {
- a = get_val();
- count_val(a);
- }
这里我们会觉得代码有些冗余
- while (a = get_val(), count_val(a), a>0) {
- //业务处理
- }
改成这样大家会发现代码明显就精简了一些。
表达式的整型运算要在 CPU 的相应运算器件内执行, CPU 内整型运算器 (ALU) 的操作数的字节长度 一般就是int 的字节长度,同时也是 CPU 的通用寄存器的长度。 因此,即使两个char 类型的相加,在 CPU 执行时实际上也要先转换为 CPU 内整型操作数的标准长度。通用 CPU ( general-purpose CPU )是难以直接实现两个 8 比特字节直接相加运算(虽然机器指令 中可能有这种字节相加指令)。所以,表达式中各种长度可能小于int 长度的整型值,都必须先转 换为int 或 unsigned int ,然后才能送入 CPU 去执行运算。
- //实例1
- char a,b,c;
- ...
- a = b + c;
// 负数的整形提升char c1 = - 1 ;变量 c1 的二进制位 ( 补码 ) 中只有 8 个比特位:1111111因为 char 为有符号的 char所以整形提升的时候,高位补充符号位,即为 1提升之后的结果是:11111111111111111111111111111111// 正数的整形提升char c2 = 1 ;变量 c2 的二进制位 ( 补码 ) 中只有 8 个比特位:00000001因为 char 为有符号的 char所以整形提升的时候,高位补充符号位,即为 0提升之后的结果是:00000000000000000000000000000001// 无符号整形提升,高位补 0
- int main()
- {
- char a = 0xb6;
- short b = 0xb600;
- int c = 0xb6000000;
- if(a==0xb6)
- printf("a");
- if(b==0xb600)
- printf("b");
- if(c==0xb6000000)
- printf("c");
- return 0; }
- int main()
- {
- char c = 1;
- printf("%u\n", sizeof(c));
- printf("%u\n", sizeof(+c));
- printf("%u\n", sizeof(-c));
- return 0;
- }
long doubledoublefloatunsigned long intlong intunsigned intint
- int fun()
- {
- static int count = 1;
- return ++count;
- }
- int main()
- {
- int answer;
- answer = fun() - fun() * fun();
- printf("%d\n", answer);//输出多少?
- return 0;
- }
- int main()
- {
- int i = 1;
- int ret = (++i) + (++i) + (++i);
- printf("%d\n", ret);
- printf("%d\n", i);
- return 0; }