本文主要是介绍10.C语言 进制转换(思维导图版),操作符(巨细版),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
文章目录
- 一.2进制(原码、反码、补码)
- 二.2进制转10进制,8进制,16进制
- 三.10进制转2进制
- 四.移位操作符<< >>
- 4.1左移操作符 <<
- 4.2右移操作符>>
- 五.位操作符&、|、^
- 5.1 &按位与
- 5.2 | 按位或
- 5.3 ^ 按位异或
- 六.编写实现:求某数字2进制第几位
- 七.编写代码实现:求⼀个整数存储在内存中的⼆进制中1的个数。
- 八.逗号表示式
- 九.下标引用操作符[ ].
- 十.函数调用操作符
- 十一.优先级、结合性
- 十二.表达式求值
- 12.1整型提升
- 12.2算术转换
- 12.3举例问题表达式
一.2进制(原码、反码、补码)
正整数的原、反、补码都相同。
负整数的三种表⽰⽅法各不相同。
在计算机系统中,数值⼀律⽤补码来表⽰和存储。原因在于,使⽤补码,可以将符号位和数值域统⼀处理
二.2进制转10进制,8进制,16进制
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为0printf("%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=aa = a^b;//a=a^b^a=0^b=bprintf("%d %d",a,b);return 0;}
a = a^b;b = a^b;//b=a^b^b=a^0=aa = 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字节长度,运算后再截断多余位变回原来字节长度。
栗子:
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。
所以,即使操作符有优先性和结合性,但是表达式的运算顺序不能确定唯一路径。
谢谢阅读,若有不足,望指正。
这篇关于10.C语言 进制转换(思维导图版),操作符(巨细版)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!