算数操作符:

+、-、*、/、%

1、除了%操作符之外,其他的几个操作符可以作用于整数和浮点数。

2、对于/操作符如果两个操作数都为整数,执行整数除法。而只要有浮点数执行的就是浮点数除法。

3、%操作符的两个操作数必须为整数。返回的是整除之后的余数。


移位操作符:

<< 左移操作符:左边抛弃,右边补0

>> 右移操作符:算术右移:右边抛弃,左边补原符号位,负数是1,正数是0

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


警告:对于移位操作符,不要移动负数位,这个是标准未定义的。例如:

int num = 10;

num >> -1;   // error


位操作符:

​&:按位与(一假即假)

| :按位或(一真即真)

^:按位异或(相同则0,相异则1)

注意:它们的操作数必须是整数。

操作的都是二进制位


练习:

编写代码,求一个整数存储在内存中的二进制中1的个数。

#include <stdio.h>
int main()
{
int num = 0;
int count = 0;
scanf("%d", &num);
while(num)
{
if(num % 2 == 1)
{
count++;
}
num = num / 2;
}
printf("%d\n", count);
return 0;
}

上述代码仅仅只能适用于正整数,负数则出错

改进:

#include <stdio.h>
int main()
{
int num = 0;
int count = 0;
scanf("%d", &num);
int i = 0;
for(i = 0; i < 32; i++)
{
if(1 == ((num >> i) & 1))
{
count++;
}
}
printf("%d\n", count);
return 0;
}


赋值操作符:

​赋值操作符可以连续使用:a = b = x + 1


单目操作符:

++、--:

前置++,先自加后赋值使用

后置++,先赋值使用后自加


sizeof:

#include <stdio.h>
int main()
{
short s = 0;
int a = 10;
printf("%d\n", sizeof(s = a + 5)); // 2,s是short类型
printf("%d\n", s); // 0,sizeof里面放的表达式不会真实运算,所以s的值没有变化
return 0;
}


#include <stdio.h>
void test1(int arr[])
{
printf("%d\n", sizeof(arr)); // 4(32位),数组在传参的时候,真正传过去的是首元素的地址,只要是地址传过去就会用指针来接收
}
void test2(char ch[])
{
printf("%d\n", sizeof(ch)); // 4(32位),同理
}
int main()
{
int arr[10] = {0};
char ch[10] = {0};
printf("%d\n", sizeof(arr)); // 40
printf("%d\n", sizeof(ch)); // 10
test1(arr);
test2(ch);
return 0;
}


逻辑操作符:

​&& 逻辑与(关注这个数本身是真还是假,区分按位与)(一假即假)

 ||   逻辑或(关注这个数本身是真还是假,区分按位或)(一真即真)

#include <stdio.h>
int main()
{
int i = 0, a = 1,b = 2,c = 3, d = 4;
i = a++ && ++b && d++;
printf("a = %d\n b = %d\n c = %d\n d = %d\n", a, b, c, d); // 返回结果:2 3 3 5
return 0;
}


#include <stdio.h>
int main()
{
int i = 0, a = 1,b = 2,c = 3, d = 4;
i = a++ || ++b || d++;
printf("a = %d\n b = %d\n c = %d\n d = %d\n", a, b, c, d); // 返回结果:2 2 3 4
return 0;
}


结构成员:​

#include <stdio.h>
// 创建一个结构体类型-struct Stu
struct Stu
{
char name[20];
int age;
char id[20];
};
int main()
{
//使用struct Stu这个类型创建了一个学生对象s1,并初始化
struct Stu s1 = {"张三", 20, "20061136"};
printf("%s\n", s1.name);
printf("%d\n", s1.age);

// 用指针的形式打印
struct Stu* ps = &s1;
printf("%s\n", (*ps).name);
printf("%d\n", (*ps).age);

// 结构体指针指向操作符的写法:结构体指针 -> 成员
printf("%s\n", ps -> name);
printf("%d\n", ps -> age);
return 0;
}


练习题:

​题目:统计二进制中1的个数,写一个函数返回二进制中1的个数

#include <stdio.h>
int count_bit_one(int n) // 当输入负数时无法得到正确结果,改进:将int n写成unsigned int n
{ // 传入一个无符号整型数
int count = 0;
while(n)
{
if(n % 2 == 1)
{
count++;
}
n = n / 2;
}
return count;
}
int main()
{
int a = 0;
int count = 0;
scanf("%d", &a);
count = count_bit_one(a);
printf("%d\n", count);
return 0;
}

上述题目还可以用按位与的操作

#include <stdio.h>
int count_bit_one(int n)
{
// 每一个二进制位与1的最后一个二进制位进行按位与比较,若返回结果为1,则表明这个二进制位是1
// 按位与:一假即假
// -1
// -1的二进制:11111111111111111111111111111111
// 1的二进制: 00000000000000000000000000000001
int count = 0;
int i = 0;
for(i = 0; i < 32; i++)
{
if(((n >> i) & 1) == 1) // 每一次向右移一位
{
count++;
}
}
return count;
}
int main()
{
int a = 0;
int count = 0;
scanf("%d", &a);
count = count_bit_one(a);
printf("%d\n", count);
return 0;
}

还可以用n&n-1的方法(最精简的一种写法)

#include <stdio.h>
int count_bit_one(int n)
{
int count = 0;
while(n)
{
n = n & (n - 1); // 自行理解......
count++;
}
return count;
}
int main()
{
int a = 0;
int count = 0;
scanf("%d", &a);
count = count_bit_one(a);
printf("%d\n", count);
return 0;
}


题目:求二进制中不同位的个数,两个int(32)整数m和n的二进制表达式中,有多少个位(bit)不同?

#include <stdio.h>
int get_diff_bit(int m, int n)
{
int tmp = m ^ n;
int self_count = 0;
while(tmp)
{
tmp = tmp & (tmp - 1);
self_count++;
}
return self_count;
}
int main()
{
int m = 0;
int n = 0;
int count = 0;
scanf("%d%d", &m, &n);
count = get_diff_bit(m, n);
printf("count = %d\n", count);
return 0;
}


题目:打印二进制的奇数位和偶数位

#include <stdio.h>
void print(int m)
{
int i = 0;
printf("奇数位:\n");
for(i = 30; i >= 0; i -= 2)
{
printf("%d ", (m >> i) & 1);
}
printf("\n");
printf("偶数位:\n");
for(i = 31; i >= 1; i -= 2)
{
printf("%d ", (m >> i) & 1);
}
printf("\n");
}
int main()
{
int m = 0;
scanf("%d", &m);
print(m);
return 0;
}