操作符详解

1.操作符

分类:
算数操作符
移位操作符
位操作符
赋值操作符
单目操作符
关系操作符
逻辑操作符
条件操作符
逗号表达式
下表引用,函数调用和结构成员

1.0算数操作符

+   -   *   / %

1.除了%操作符外,其他的几个操作符可以作用于整数和浮点数。
2.对于/操作符如果两个操作数都为整数,执行整数除法,而只要有浮点数执行的就是浮点数除法。
3.%操作符的两个操作数必须为整数,返回的是整除之后的余数。

#include<stdio.h>
int main()
{
	int a = 5 / 2;//商2余1
	//int a = 5 / 2.0;
	//int a=8%2;
	printf("a=%d\n",a);
	return 0;
}

1.1移位操作符

1.<<左移操作符规则:左边抛弃,右边补0

#include<stdio.h>
int main()
{
	int a = 5;
	int b = a << 1;
	//00000000 00000000 00000000 00000101
	printf("%d\n,b");
	return 0;
}

2 >>右移操作符:
算术右移:右边丢弃,左边补原符号位
逻辑右移:右边丢弃,左边补0

#include<stdio.h>
int main()
{
	int a = 16;
	//>>-右移操作符
	//00000000 00000000 00000000 00010000
	int b=a >> 1;
	return 0;
}
#include<stdio.h>
int main()
{
	int a = -1;
	//整数的二进制表示有:原码,反码,补码
	//存储到内存的是补码
	//10000000 00000000 00000000 00000001-原码
	//11111111 11111111 11111111 11111110-反码
	//11111111 11111111 11111111 11111111-补码
	int b = a >> 1;
	printf("%d\n", b);
	return 0;
}

3.对于移位操作符,不要移动负数位,这个是标准未定义的。

1.2位操作符

1.位操作符有:
& 按位与
| 按位或
^按位异或
他们的操作数必须是整数
2.代码:
按位与:

#include<stdio.h>
int main()
{
	int a = 3; 
	int b = 5;
	//00000000 00000000 00000000 00000011
	//00000000 00000000 00000000 00000101
	//00000000 00000000 00000000 00000001
	int c = a&b;
	printf("%d\n",c);
	return  0;
}

按位或:

#include<stdio.h>
int main()
{
	//|按位或
	int a = 3;
	int b = 5;
	//00000000 00000000 00000000 00000011
	//00000000 00000000 00000000 00000101
	//00000000 00000000 00000000 00000111
	int c = a | b;
	printf("%d\n", c);
	return 0;
}

按位异或:

#include<stdio.h>
int main()
{
	//^按位异或
	//按二进制位异或
	//相同为0,相异为1
	int a = 3;
	int b = 5;
	//00000000 00000000 00000000 00000011
	//00000000 00000000 00000000 00000101
	//00000000 00000000 00000000 00000110
	int c = a ^ b;
	printf("%d\n", c);
	return 0;
}

3.应用:
不能创建临时变量(第三个变量),实现两个数的交换:

#include<stdio.h>
int main()
{
	int a = 10;
	int b = 20;
	a = a^b;
	b = a^b;
	a = a^b;
	printf("a=%d b=%d\n", a, b);
	return 0;
}

编写代码,求一个整数存储在内存中的二进制的个数:
方法一:

#include<stdio.h>
//这种方法不能计算负数
int main()
{
	int num = 10;
	int count = 0;
	while (num)
	{
		if (num % 2 == 1)
			count++;
		num = num / 2;
	}
	printf("二进制中1的个数=%d\n", count);
	return 0;
}

方法二:

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

1.3赋值操作符

1.赋值操作符:

#include<stdio.h>
int main()
{
	int weight = 120;//体重
	weight = 89;//重新赋值
	double salary = 1000.0;
	salary = 2000.0;//使用赋值操作符赋值
	//赋值操作符可以连续赋值
	int a = 10;
	int x = 0;
	int y = 20;
	a = x = y + 1;//连续赋值
	return 0;
}

2.复合赋值符:
+= -= *= /= %= >>= <<= &= |= ^=

#include<stdio.h>
int main()
{
	int a = 10;
	a = a + 2;
	a += 2;//复合赋值符
	a=a >> 1;
	a >>= 1;
	a = a & 1;
    a &= 1;
	return 0;
}

1.4单目操作符

1.单目操作符的意思是只有一个操作数。
2.单目操作符有:
在这里插入图片描述
3.代码如下:

#include<stdio.h>
int main()
{
	1.逻辑反操作
	int a = 0;
	if (!a)
	{
		printf("哈哈\n");
	}
	int a = 10;
	printf("%d\n", !a);

	2.-负值
	int a = 5;
	a = -a;

	3.&-取地址操作符
	int a = 10;
	int*p=&a;
	*p;//解引用操作符

	4.sizeof-求变量,类型所占内存空间的大小,单位是字节
	int a = 10;
	char c = 'r';
	char* p = &c;
	int arr[10] = { 0 };
	printf("%d\n", sizeof(a));//4
	printf("%d\n", sizeof(c));//1
	printf("%d\n", sizeof(p));//4
	printf("%d\n", sizeof(arr));//40

	5.~-对一个数的二进制按位取反
	00000000 00000000 00000000 00000000
	11111111 11111111 11111111 11111111-补码
	11111111 11111111 11111111 11111111-反码
	10000000 00000000 00000000 00000001-原码
	int a = 0;
	printf("%d\n", ~a);//-1

	int a=11;
	a = a | (1 << 2); 
	printf("%d\n", a);
	a = a&(~(1 << 2));
	printf("%d\n", a);

	6.++前置和后置
	int a = 10;
	printf("%d\n", ++a);//前置++,先++,后使用
	printf("%d\n", a++);//后置++,先使用,再++

	7.*间接访问操作符

	8.(类型)-强制类型转化
	int a = (int)3.14;
	return 0;
}

4.练习:
sizeof和数组:

#include<stdio.h>
void test1(int arr[])
{
	printf("%d\n", sizeof(arr));//4
}
void test2(char ch[])
{
	printf("%d\n", sizeof(ch));//4
}
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;
}

1.5关系操作符

>  >=  <  <=   !=(用于测试不相等)  ==(用于测试相等)

1.6逻辑操作符

1.逻辑操作符有
&&逻辑与 ||逻辑或

include<stdio.h>
int main()
{
	int a = 3;
	int b = 5;
	int c = a && b;
	//int c=a ||b;
	printf("%d\n", c);
	return 0;
}

2.逻辑与和或的特点:

#include<stdio.h>
int main()
{
	int i = 0, a = 0, 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);//1 2 3      4
	return 0;
}

1.7条件操作符

1.exp1?exp2:exp3
2.练习:
求两个数的较大值:

#include<stdio.h>
int main()
{
	int a =10;
	int b =20;
	int max = 0;
	max = (a > b ? a : b);
	printf("%d\n", max);
	return 0;
}

1.8逗号表达式

1.exp1,exp2,exp3,…expn
逗号表达式,就是用逗号隔开的多个表达式,逗号表达式,从左向右依次执行,整个表达式的结果是最后一个表达式的结果。

#include<stdio.h>
int main()
{
	int a = 1;
	int b = 2;
	int c = (a > b, a = b + 10, a, b=a + 1);
	printf("%d\n", c);//13
	return 0;
}

1.9下标引用,函数调用和结构成员

1.[]下标引用操作符
操作数:一个数组名+索引值

int arr[10];//创建数组
arr[9]=10;//使用下标引用操作符
[]的两个操作数是arr和9

2.()函数引用操作符,接受一个或者多个操作数:第一个操作数是函数名,剩余的操作数就是传递给函数的参数。

#include<stdio.h>
int get_max(a, b)
{
	return(a > b ? a : b);
}
int main()
{
	int a = 10;
	int b = 20;
	int max = get_max(a, b);
	printf("max=%d\n", max);
	return 0;
}

3.结构体访问操作符.:
.:结构体.成员名
->:结构体指针->成员名

#include<stdio.h>
//创建一个结构体类型-struct stu
struct stu
{
    //成员变量
	char name[20];
	int age;
	char id[20];
};
int main()
{
	//使用sturuct stu类型创建了一个学生对象s1,并初始化
	struct stu s1 = { "张三",20,"2019234" };
	struct stu* ps=&s1;
	printf("%s\n", s1.name);
	printf("%d\n",ps->age);
	return 0;
}

2表达式求值

表达式求值的顺序一部分是由操作符的优先级和结合性决定,也有些表澳大使的操作数在求值的过程中可能需要转化为其他类型。

2.1隐形类型转化

1.c的整型算数运算总是至少以缺省整形类型的精度来进行的。
为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转化为普通整型,这种转化称为整型提升。
2.整型提升的意义:
表达式的整形运算要在CPU的相应运算器内执行,CPU内整型运算器的操作数的字节长度一般就是int的字节长度,同时也是CPU的通用寄存器的长度。
因此,即使两个char类型的相加,在CPU执行时实际上也要先转化为CPU内整型操作数的标准长度。
通用CPU是难以直接实现两个8比特字节直接相加运算(虽然机器指令中可能有这种字节相加指令)。所以,表达式中各种长度可能小于int长度的整形值,都必须先转化为int或者unsigned int,然后才能送入CPU去执行运算。
3.如何进行整型提升呢?
有符号整形提升的时,高位补充符号位
无符号数整形提升时,高位补充0.
整形提升是按照变量的数据类型的符号位来提升的
4.代码如下:

#include<stdio.h>
int main()
{
	char a = 3;
	//00000011-a
	//00000000 00000000 00000000 00000011整形提升
	//01111111-b
	//00000000 00000000 00000000 01111111整形提升
	//00000000 00000000 00000000 10000010
	//10000010-c
	//11111111 11111111 11111111 10000010整形提升-补码
	//11111111 11111111 11111111 10000001-反码
	//10000000 00000000 00000000 01111110-原码  -126
	char b = 127;
	char c = a + b;
	printf("%d\n", c);
	return 0;
}

2.2算术转化

如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数的转化为另一个操作数的类型,否则操作就无法进行。下面的层次体系称为寻常算术转化。
long double
double
float
unsigned long int
long int
unsigned int
int
如果某个操作数的类型在上面这个列表中排名较低,那么首先要转化为另一个操作数的类型后执行运算。

2.3操作符的属性

复杂表达式的求值有三个影响的因素:
1.操作符的优先级。
2.操作符的结合性。
3.是否控制求值顺序。

2.4应用

1.求一个整数存储在内存中1的个数:
方法一:

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

方法二:

#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;
	scanf_s("%d", &a);
	int count=count_bit_one(a);
	printf("count=%d\n", count);
	return 0;
}

2.求二进制不同位的个数,两个int整数m和n的二进制表达中,有多少个位(bit)不同:

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

3.获取一个整数二进制序列中所有的偶数位和奇数位,分别打印二进制序列:

#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_s("%d", &m);
	print(m);
	return 0;
}

4.写一个函数打印arr数组内容,不使用数组下标,使用指针,arr是一个整形一维数组:

#include<stdio.h>
void print(int *p, int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", *(p + i));
	}
}
int main()
{
	int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	print(arr,sz );
	return 0;
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ZJHFOREVERZJ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值