10.C语言 进制转换(思维导图版),操作符(巨细版)

一.2进制(原码、反码、补码)

正整数的原、反、补码都相同。
负整数的三种表⽰⽅法各不相同。

整数的2进制
表示方法
原码
反码
补码
三种表示方法
符号位
0表示正数
1表示负数
数值位
最高的一位是符号位
剩余的都是数值位
«原码»
1
直接将数值按照正负数的形式翻译成的二进制
«反码»
2
符号位不变,其他位依次按位取反
«补码»
3
反码+1
(对于整形来说:内存存放的数据是补码)

在计算机系统中,数值⼀律⽤补码来表⽰和存储。原因在于,使⽤补码,可以将符号位和数值域统⼀处理

二.2进制转10进制,8进制,16进制

例如
2进制
满2进1
每一位由0到1的数字组成
1101
10进制
满10进1
每一位由0到9的数字组成
8进制
每一位由0到7的数字组成
16进制
每一位由0到9和a到f的数字组成
a到f可以看作10到15

2进制转10进制举例:
在这里插入图片描述
2进制转8进制:
从2进制序列中右边低位开始向左每3个2进制位会换算⼀个8进制位,剩余不够3个2进制位的直接换算.
0开好头的数组,会被当做8进制。

在这里插入图片描述
2进制转16进制:
从2进制序列中右边低位开始向左每4个2进制位会换算⼀个16进制位,剩余不够4个⼆进制位的直接换算。
16进制的数字每⼀位是0~9,a ~f 的,16进制表⽰的时候前⾯加0x
在这里插入图片描述

三.10进制转2进制

在这里插入图片描述

四.移位操作符<< >>

操作数只能是整数
对于移位运算符,不要移动负数位

4.1左移操作符 <<

规则:左边丢弃,右边补0(操作数的二进制)
在这里插入图片描述
在这里插入图片描述

int main()
{
	int a = 10;
	int b = a << 1;
	printf("a=%d ", a);//a没变
	printf("b=%d ", b);
	a = -10;
	int c = a << 1;
	printf("c=%d \n", c);
	return 0;
}

4.2右移操作符>>

逻辑右移:右边丢弃,左边补0
算术右移:右边丢弃,左边补原符号位
用上面哪一个右移取决于编译器,大部分编译器采用算术右移。
在这里插入图片描述

int main()
 {
	int num = -1;
	int n = num >> 1;
	printf("%d",n);
	return 0;
}

五.位操作符&、|、^

& 按位与
| 按位或
^ 按位异或
按位:按二进制位
操作数只能是整数

5.1 &按位与

规则:都为1才是1,有0就是0

int main()
{
	int a = 5;
	int b = -6;
	int c = a & b;//写出a和b的二进制位都是1为1,有0为0
	printf("%d",c);
	return 0;
}

结果为0
在这里插入图片描述

在这里插入图片描述

5.2 | 按位或

规则: 都是0才为0,有1就是1

int main()
{
	int a = 5;
	int b = -6;
	int c = a | b;
	printf("%d", c);
	return 0;
}

结果为-1
在这里插入图片描述

5.3 ^ 按位异或

规则:二进制相同为0,不同为1

int main()
{
	int a = 5;
	int b = -6;
	int c = a ^ b;
	printf("%d",c);
	return 0;
}

结果为-1
在这里插入图片描述

不创建第三个变量,实现两个变量值交换
原理:
(1)一个变量按位异或自己结果是0,即a^a=0;
(2)一个变量按位异或0结果为自己,即a^0=a;

int main()
 {  
       int a = 4;
       int b = 6;
       a = a^b;
	   b = a^b;//b=a^b^b=a^0=a
	   a = a^b;//a=a^b^a=0^b=b
      printf("%d %d",a,b);
  return 0;
 }
   a = a^b;
   b = a^b;//b=a^b^b=a^0=a
   a = a^b;//a=a^b^a=0^b=b

异或只能用作整数交换,代码可读性较低,效率低于创建变量的方法

六.编写实现:求某数字2进制第几位

求21的二进制第4位

int main()
	{
		int a = 21;
		int b = (a >> 4 & a);
		printf("%d", b);
		return 0;
	}

结果为1
在这里插入图片描述

七.编写代码实现:求⼀个整数存储在内存中的⼆进制中1的个数。

第一种方法:

#include<stdio.h>
int main()
{
	int num = 0;
	scanf("%d",&num);
	int i = 0;
	int count = 0;
	for (i = 0; i < 32; i++)
	{
		if ((num >> i) & 1) 
			count++;
	}
	printf("%d的二进制中1的个数是%d",num,count);
	return 0;
}

在这里插入图片描述
但是会循环32次,继续优化。
第二次方法:

#include<stdio.h>
int main()
{
	int num = 0;
	scanf("%d",&num);
	int i = 0;
	int count = 0;
	while (num)
	{
		count++;
		num = num & (num - 1);
	}
	printf("二进制中1的个数是%d",count);

	return 0;
}

在这里插入图片描述

八.逗号表示式

规则:用逗号隔开的多个表达式,从左到右执行,整个表达式结果是最后一个表达式的结果。

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

在这里插入图片描述

九.下标引用操作符[ ].

操作数:一个数组名 + 一个索引值

int arr[100];
arr[19]=10;

[ ]两个操作数是arr和9

十.函数调用操作符

接受一个或多个操作数:
第一个操作数:函数名
剩余操作数:传递给函数的参数
栗子:

#include<stdio.h>
void test1()
{
	printf("hehe\n");
}
void test2(int a)
{
	printf("%d\n",a);
}

int main()
{
	test1();
	int x = 10;
	test2(x);

	return 0;
}

十一.优先级、结合性

操作符的两个属性决定了表达式求值计算顺序
优先级
如果一个表达式有多个运算符,要看哪个运算符应该优先执行。
结合性
当运算符的优先级相同时,优先级无法决定先计算哪个,于是我们就要看是左结合还是右结合。大部分是左结合,从左到右。
我们需要记住这些操作符优先级,其他遇到查表就行:

  • 圆括号()
  • 自增运算符++ 自减运算符 - -
  • 一元运算符+和-
  • 乘法 * 除法 /
  • 加法+ 减法-
  • 关系运算符> <等
  • 赋值运算符=
    圆括号优先级最高,可以用它改变其他运算符优先级
    优先级和结合性表格:
    在这里插入图片描述
    https://zh.cppreference.com/w/c/language/operator_precedence
3*2/5;

*和/的优先级一样,结合性都是从左到右,所以从左到右算。

十二.表达式求值

表达式求值前要就行类型转换,当表达式的值换到适当的类型,才开始计算。

12.1整型提升

C语言整型算术运算总是至少以缺省整型类型的精度进行。
在这里插入图片描述
为了获得这个精度,表达式中的字符char 和短整型 short 操作数在使用之前被转换为普通整型(int 或 unsigned int),这种转换叫做整型提升
char和short类型太小了,不能直接拿来执行运算,得先变长成int字节长度,运算后再截断多余位变回原来字节长度。

如何进行整型提升
有符号整型
前面8*3位补符号位
无符号整型
前面8*3位补0

栗子:

char a=3;
char b=127;
char c=a+b;
printf("c=%d",c);
   3 :  00000000 00000000 00000000 00000011(补码)
  127:  00000000 00000000 00000000 01111111(补码)
3+127:  00000000 00000000 00000000 10000010(补码)
%d:打印整型,整型提升

c发生截断: 10000010(补码)
又正数原码反码补码相同,
负数转码规则: 原码取反转反码 ,反码+1转补码
因为我们得到的是补码,所以提升要注意我们的是有符号还是符号进行区分补位。
10000010(有符号前补符号位1)
提升:1111 1111 1111 1111 1111 1111 1000 0010(补码)
提升完成,当我们想看最后结果,则进行下面转换成原码:
1111 1111 1111 1111 1111 1111 1000 0001(补码-1得到反码)
1000 0000 0000 0000 0000 0000 0111 1110(取反得到原码)
原码转换10进制是 -126

12.2算术转换

如果某个操作符的各个操作数属于不同的类型,
那么除非其中一个操作数转换为另一个操作数的类型,
否则操作就无法进行。
寻常算术转换如下:
1.long double
2.double
3.float
4.usigned long int
5.long int
6.unsigned int
7.int

排名越靠后的类型,首先要转换为另外一个操作数类型后执行运算。

12.3举例问题表达式

a*b+c*d+e*f

优先级不能决定第三个*比第一个+早执行
2.

c+--c;

优先级只能保证自减–在+前面执行,但是+的左操作数在右操作数之前还是之后,并不确定。
3.

int main()
{
  int i=10;
  i=i-- - --i *(i=-3)* i++ + ++i;
  printf("i = %d\n",i);
  return 0;
}

在不同编译器下,有不同结果。
4.

int fun()
{
	static int count = 1;
	return ++count;
}
int main()
{
	int answer;
	answer = fun() - fun() * fun();
	printf("%d\n",answer);
	return 0;
}

虽然大多数编译器结果都一样,但是代码有问题。
answer = fun() - fun() * fun();我们只能通过优先级知道✖号比➖号先执行,但是函数调用先后顺序不知道。
5.

int main()
{
	int i = 1;
	int ret = (++i) + (++i) + (++i);
	printf("%d\n",ret);
	printf("%d\n",i);
	return 0;
}

第一个在➕执行时,不知道第三个前置➕➕有没有执行,无法知道先后顺序。
所以它在VS2022结果是12 4,在gcc编译器是10 4。

所以,即使操作符有优先性和结合性,但是表达式的运算顺序不能确定唯一路径。
谢谢阅读,若有不足,望指正。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值