目录
1.操作符分类
2.算数操作符 + - * / %
a.对于除法来说:
(1)整数除法(两边都是整数)
(2)浮点数除法(只要除号一边又浮点数就执行浮点数除法,得出来的结果是浮点数)
(3)除数不能为0
int main()
{
int r = 7 / 2;
printf("%d\n", r);
double d = 7 / 2;
printf("%lf\n", d);//3.5?
return 0;
}
运行结果如下
d的计算中,因为/左右两边都是整数,所以结果还是取商
要算出3.5 要采用浮点数的方法
b.%是取模负号,%的两边必须是整数
3.移位操作符
<<左移操作符 >>右移操作符
注意:移位操作符的操作数只能是整数
一般来说,计算机能够处理的是二进制信息,所以当我们输入一个十进制整数的时候,电脑会自动将他转换成2进制来操作
整数的二进制有三种表示形式
原码,反码,补码
1.正整数的原码、反码、补码是相同的
2.负的整数原码、反码、补码是要通过计算的
以15为例子举例
int a = 15;//1111
1个整型是4个字节 = 32bit位,所以我们要把它补成32位
对于正整数来说,符号位第一位是0
00000000000000000000000000001111 - 原码
00000000000000000000000000001111 - 反码
00000000000000000000000000001111 - 补码
对于负数来说(以-15为例)符号位第一位是1
10000000000000000000000000001111 - 原码
11111111111111111111111111110000 - 反码(原码的符号位不变,其他按位取反得到的就是反码)
11111111111111111111111111110001 - 补码(反码+1就是补码)
注意:整数在内存中存储的是补码,计算的时候也是用补码来计算的
右移有除二的效果
移位移动的是补码的二进制序列
int main()
{
int a = 15;
int b = a >> 1;
printf("%d\n", b);//7
printf("%d\n", a);
return 0;
}
int main()
{
int a = -15;
int b = a >> 1;
printf("%d\n", b);
printf("%d\n", a);
return 0;
}
右移
算术右移:(右边丢弃,左边补原来的符号位,正补0,负补1)
逻辑右移:(右边丢弃,左边直接补0)
C语言没有明确规定用的是算术右移还是逻辑右移,一般编译器上采用算数右移
左移的话,直接在末尾加一个0就行
4.位操作符
& 按位与
| 按位或
^按位异或
应用:
不用中间变量交换两个整型的值
这个是怎么实现的呢
int main()
{
int a = 3;
int b = 5;
//a ^ a = 0
//a ^ 0 = a
//异或是支持交换律的
//a ^ b ^ a
//011 a
//101 b
//110 a ^ b
//011 a
//101 (a ^ b) ^ a
//a ^ a ^ b = 5
a = a ^ b;
b = a ^ b;//(a ^ b) ^ b = a
a = a ^ b;//a ^ (a ^ b) = b
return 0;
}
编写代码实现:求一个整数存储在内存中的二进制中1的个数
1. 整数有32个bit位
2. 获得32个bit位的每一位
3. 判断这一位是否为1
4. 是1就计数器+1
#include <stdio.h>
int countOnes(unsigned int num)
{
int count = 0;
while (num != 0)
{
count += num & 1; // 判断最低位是否为1
num >>= 1; // 将num右移一位,相当于去掉了最低位
}
return count;
}
int main()
{
unsigned int num;
scanf("%u", &num);
printf("%d\n", countOnes(num));
return 0;
}
5.单目操作符
! - 逻辑反操作
& - 取地址 * - 解引用操作符 运用于指针
int main()
{
int a = 10;
//pa是指针变量
int* pa = &a;//&-取地址操作符-取出a的地址
*pa = 20;//解引用操作符(间接访问操作符)-单目操作符-通用pa中存放的地址,找到指向的空间(内容)
int c = *pa;
return 0;
}
sizeof (1)不是函数,是操作符
(2)计算的是类型创建变量的大小,单位是字节
int main()
{
int a = 10;
printf("%d\n", sizeof(int));//4
printf("%d\n", sizeof(a));//4
printf("%d\n", sizeof a);//4
//说明sizeof不是函数,因为一般函数必须带括号加形参
return 0;
}
int main()
{
int arr[10] = {0};
printf("%d\n", sizeof(arr));//40 - 计算整个数组的大小,单位字节
printf("%d\n", sizeof(int [10]));//40
return 0;
}
~补码按二进制位取反(其实就是在每一位中0变1,1变0)
//int main()
//{
// int a = 0;
// printf("%d\n", ~a);
// //00000000000000000000000000000000
// //11111111111111111111111111111111 - 补码
// //11111111111111111111111111111110
// //10000000000000000000000000000001 //-1
// return 0;
//}
int main()
{
int a = 13;
a |= (1 << 4);
//00000000000000000000000000001101
//00000000000000000000000000010000 -- (1 << 4)
//00000000000000000000000000011101 -- a | (1 << 4) = 29
printf("%d", a);
a &= (~(1 << 4));
printf("%d", a);//13
return 0;
}
三种循环输入方式
//int main()
//{
// int a = 0;
// while (scanf("%d", a) == 1)
// {
// printf("%d", a);
// }
// return 0;
//}
//int main()
//{
// int a = 0;
// scnaf 读取失败返回EOF
// while (scanf("%d", a) != EOF)
// {
// printf("%d", a);
// }
// return 0;
//}
//int main()
//{
// int a = 0;
// scnaf 读取失败返回EOF
// 假设scanf读取失败,返回EOF --> EOF = -1
// while (~scanf("%d", a))
// {
// printf("%d", a);
// }
// return 0;
//}
++和--
//--前置,后置--
//++前置,后置++
//int main()
//{
// int a = 1;
// int b = a++;//后置++,先使用,后++
// //b = a, a = a + 1
// printf("a = %d, b = %d", a, b);//2 1
// return 0;
//}
//int main()
//{
// int a = 1;
// int b = a--;//后置--,先使用,后--
// //b = a, a = a - 1
// printf("a = %d, b = %d", a, b);//0 1
// return 0;
//}
int main()
{
int a = 1;
int b = ++a;//前置++,先++,后使用
//a = a + 1, b = a
printf("a = %d, b = %d", a, b);//2 2
return 0;
}
前置--跟前置++道理相同,不再赘述
强制类型转换
练习
下列代码输出结果是啥?
答案
6.关系操作符
7.逻辑操作符
int main()
{
int a = 0;
int b = 0;
scanf("%d %d", &a, &b);
//a 和 b 都是5就打印hehe 两个都得满足才打印hehe
if (a == 5 && b == 5)
{
printf("hehe\n");
}
//a或者b是5就打印haha 一个满足就能打印haha
if (a == 5 || b == 5)
{
printf("haha\n");
}
return 0;
}
练习
打印结果是啥
#include <stdio.h>
int main()
{
int i = 0, a = 0, b = 2, c = 3, d = 4;
i = a++ && ++b && d++;
printf("a = %d\nb = %d\nc = %d\nd = %d\n", a, b, c, d);
int i = 0, a = 1, b = 2, c = 3, d = 4;
i = a++ && ++b && d++;//a++
printf("a = %d\nb = %d\nc = %d\nd = %d\n", a, b, c, d);
int i = 0, a = 0, b = 2, c = 3, d = 4;
i = a++ || ++b || d++;
printf("a = %d\nb = %d\nc = %d\nd = %d\n", a, b, c, d);//1 3 3 4
return 0;
}
答案和分析
#include <stdio.h>
int main()
{
//int i = 0, a = 0, b = 2, c = 3, d = 4;
//i = a++ && ++b && d++;//a++ +使用前= 0为假,
//&& 操作符,左边为假,右边就不计算了!
//printf("a = %d\nb = %d\nc = %d\nd = %d\n", a, b, c, d);// 1 2 3 4
//int i = 0, a = 1, b = 2, c = 3, d = 4;
//i = a++ && ++b && d++;//a++ +使用前=1为真,后面继续计算
//printf("a = %d\nb = %d\nc = %d\nd = %d\n", a, b, c, d);
// a = 2(因为a在前面已经使用过了,所以这里加上1等于2)
//b = 3 c = 3 d = 5
int i = 0, a = 0, b = 2, c = 3, d = 4;
i = a++||++b||d++;// || 左右两边有一个是真就可以计算
printf("a = %d\nb = %d\nc = %d\nd = %d\n", a, b, c, d);//1 3 3 4
return 0;
}