操作符讲解

目录

二进制和进制转换

原码、反码、补码

移位操作符

位操作符

一道面试题:

练习1:

思考题:

练习2:

逗号表达式

函数调用操作符()

结构成员访问操作符

结构体

操作符的属性:优先级、结合性

优先级:

结合性:


二进制和进制转换

  • 2进制转8进制

8进制的数字每一位是0~7,0~7的数字各自写成2进制,最多有3个2进制位就够了,比如7的2进制位是111,所以2进制转8进制的时候,从2进制序列中右边低位开始向左每3个2进制位换算成一个8进制位,剩余不够3个2进制位的直接换算

如:2进制的01101011,换成8进制0153,0开头的数字会被当作8进制

  • 2进制转16进制

16进制的数字每一位是0~9,a~f的数字,各自写成2进制,最多有4个2进制位就足够了,比如f的二进制是1111,所以2进制转16进制的时候,从2进制序列中右边低位开始向左每4个2进制位会换算一个16进制位,剩余不够4个二进制位的直接换算

如:2进制的01101011,换成16进制0x6b,16进制表示的时候前面加0x

原码、反码、补码

整数的2进制表示方法有三种,即原码、反码和补码

有符号整数的三种表示方法均有符号位和数值位两部分,2进制序列中,最高位的一位被当做是符号位,剩余的都是数值位

符号位0表示正,1表示负

正整数的原、反、补码都相同

负整数的三种表示方法各不相同

对于整型来说,数据存放内存中存放的是补码;原因:在计算机系统中,数值一律用补码来表示和存储,使用补码,可以将符号位和数值域统一处理,同时,加法和减法也可以统一处理(CPU只有加法器)此外,补码和原码相互转换,其运算过程是相同的(补码取反加一得到原码),不需要额外的硬件电路

移位操作符

  • 左移操作符:左边抛弃,右边补0
#define _CRT_SECURE_NO_WARNINGS
#include 
int main()
{
	int a = 6;
	int b = (a << 1);
	printf("%d\n", a);
	printf("%d\n", b);
	return 0;
}

运行结果:

a本身不变

  • 右移操作符:

右移分两种:1.逻辑右移:左边用0填充,右边丢弃

                      2.算术右移:左边用原该值的符号位填充,右边丢弃(推荐)

位操作符

&按位与           &&逻辑与

|按位或              ||逻辑或

^按位异或:相同为0,相异为1

~按位取反         !逻辑取反

他们的操作数必须是整数 

一道面试题:

  • 最先想到的方法:
#define _CRT_SECURE_NO_WARNINGS
#include 
//不添加变量,实现两个数的交换
int main()
{

	int a = 1, b = 2;
	a = a + b;
	b = a - b;
	a = a - b;
	printf("a=%d,b=%d", a, b);
	return 0;
}

运行结果:

此方法有一个弊端,如果两个数很大,就超出了整型的范围

  • 用另一种方法(按位异或):
#define _CRT_SECURE_NO_WARNINGS
#include 
//不添加变量,实现两个数的交换
int main()
{

	int a = 1, b = 2;
	a = a ^ b;//a相当于一把钥匙,在b处找到a,在a处找到b
	b = a ^ b;
	a = a ^ b;
	printf("a=%d,b=%d", a, b);
	return 0;
}

运行结果:

代码分析:

1^1=0;

1^0=1;

b=a^b^b=a;

a=a^b^a=b;

实现了交换,也不会溢出;

练习1:

  • 编写代码实现:求一个整数存储在内存中的二进制中1的个数
  • 首先想到的方法:
#define _CRT_SECURE_NO_WARNINGS
#include 
int main()
{
	unsigned int n;//正负数都可以!
	scanf("%d", &n);
	int count = 0;
	while (n)
	{
		if (n % 2 == 1)
			count++;
		n /= 2;
	}
	printf("%d", count);
	return 0;
}

但是此方法如果不是unsigned,则不适用于负数

  • 另一种方法:
int main()
{
	unsigned int n;
	scanf("%d", &n);
	int count = 0;
	while (n)
	{
		if (n & 1 == 1)
			//如果一个数最后一位是1,则得到的数为1,否则为0;
			//逻辑与&
			count++;
		//n /= 2;//将最后一位去除,也就是右移一位,即,下面一句话
		n >>= 1;
	}
	printf("%d", count);
	return 0;
}
  • 另一种方法(不需要unsigned):(不在乎正负数)
int main()
{
	int n;
	int count = 0;
	scanf("%d", &n);
	int i = 0;
	for (i = 0; i < 32; i++)
	{
		if ((n >> i) & 1 == 1)
			count++;
	}
	printf("%d", count);
	return 0;
}
  • 还有一种方法,不易想到:

n=n&(n-1)//能将n的二进制中最右边的1去掉;

int main()
{
	int n;
	int count = 0;
	scanf("%d", &n);
	while (n)
	{
		n = n & (n - 1);
		count++;
	}
	printf("%d", count++);
	return 0;
}

思考题:

如何判断一个数是否是2的次方?

#define _CRT_SECURE_NO_WARNINGS
#include 
int main()
{
	int n;
	scanf("%d", &n);
	if ((n & (n - 1) )== 0)
		printf("yes!");
	else
		printf("no!");
	return 0;
}

练习2:

二进制位置0或者置1

编写代码将n(例如13)的二进制序列的第5位修改为1,然后再改为0

先或后与

int main()
{
	int n;
	scanf("%d", &n);
	n |= (1 << 4);//把第5位改为1
	printf("%d\n", n);
	n &= (~(1 << 4));//把第5位改为0
	printf("%d", n);
	return 0;
}

逗号表达式

逗号表达式,从左向右依次执行,整个表达式的结果是最后一个表达式的结果

#define _CRT_SECURE_NO_WARNINGS
#include 
int main()
{
	int a = 1, b = 2;
	int c = (a > b, a = b + 10, a, b = a + 1);//a=12,b=12+1=13;
	printf("%d", c);//13
	return 0;
}

函数调用操作符()

函数调用操作符的参数至少为1个,如:

void test()
{
	printf("hehe\n");
}
int main()
{
	test();//1个参数
	return 0;
}

结构成员访问操作符

结构体

C语言中有了内置类型,如char,short,int,float,但只有这些是远远不够的,为了解决这一问题,增加了结构体这种自定义的数据类型,来创造出适合的类型

结构体关键字:struct

结构体是用来描述一个复杂对象,里面可以包含多个属性

结构体中涉及2个操作符:. 和 ->,也叫成员访问操作符

结构是一些值的集合,这些值称为成员变量,结构的每个成员可以是不同类型的变量,如:标量,数组,指针,甚至是其他的结构体

结构的声明:

#define _CRT_SECURE_NO_WARNINGS
#include 
struct student
{
	char name[20];
	int age;
	int high;
	float weight;
	char id[16];//成员列表
}s4,s5,s6;//分号不能少
//s4,s5,s6是全局的结构体变量
struct student s7;//全局的
int main()
{
     struct student s1={"张三",18,180,75.5f,"2328202311"};//初始化
     struct student s2={.age=19,.name="李四",.weight=80.5,.high=177,.id="2328202312"};
     //结构体变量.成员名
     struct student s3;//局部的
     printf("%s %d %d %.1f %s\n",s1.name,s1.age,s1.high,s1.weight,s1.id);
}

操作符的属性:优先级、结合性

C语言的操作符有2个重要的属性:优先级、结合性,这两个属性决定了表达式求值的计算顺序

优先级:

操作符讲解_第1张图片

结合性:

如果两个运算符优先级相同,则需看结合性,根据运算符是左结合还是右结合,大部分运算符是左结合(从左到右执行)

圆括号()的优先级最高,可以使用它改变其他运算符的优先级

你可能感兴趣的:(c语言)