05操作符和表达式
Posted 再吃一个橘子
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了05操作符和表达式相关的知识,希望对你有一定的参考价值。
1.操作符
分类:
- 算术操作符
- 移位操作符
- 位操作符
- 赋值操作符
- 单目操作符
- 关系操作符
- 逻辑操作符
- 条件操作符
- 逗号表达式
- 下标引用、函数调用和结构成员
1.1算数操作符
+ - * / %
1. 除了 % 操作符之外,其他的几个操作符可以作用于整数和浮点数。
2. 对于 / 操作符如果两个操作数都为整数,执行整数除法。而只要有浮点数执行的就是浮点数除法。
3. % 操作符的两个操作数必须为整数。返回的是整除之后的余数。
int a = 9 / 2;
double b = 9 / 2;
printf("%d,%lf\\n", a, b);//4,4.000000
//对于 /(除号)来说,两边都是整数,执行整数除法,和接收的数据类型无关
//操作数中有浮点数,才执行浮点数除法
double c = 9 / 2.0;
printf("%lf", c);//4.500000
// % 得余数
// % 取模只能能针对整数类型
int d = 9 % 2;
printf("%d ", d);
//int e = 9.0 % 4.0;//报错
1.2移位操作符
<< 左移操作符
>> 右移操作符
1.2.1左移操作符<<
左移操作符移位规则:左边丢弃,右边补0.
步骤:(假设求 值a 左移x位)
- 写出a的二进制原码,由原码求出反码,补码。
- 将补码左移x位,右边补x个0,得到左移运算符之后的数的补码。
- 将该数的补码转换成反码,再进而转换成原码,得到最终求解结果。
见左移运算符的代码,注释内容~~~,来深刻理解:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
// >> —— 右移操作符
//
// << —— 左移操作符
//左边丢弃,右边补0
//左移操作符
int a = 5;
int b = a << 1;
printf("%d\\n", b);//打印的是原码,在计算机中存储的是补码
//移位操作符,移动的是二进制位
//对于整数的二进制有3中表现形式:原码,反码,补码。
//整数在内存中的存储 —— 二进制的补码
//正整数 —— 原码,反码,补码相同
//负整数 ——
//原码:直接按照数字的正负写出的二进制序列
//反码:原码的符号位不变,其他位按位取反
//补码:反码 + 1
//正数
//比如:对于a = 5来说,是个整数,而整数占4个byte,32个bit位:
//原码:0 00000000000000000000000000000000101
//反码:0 00000000000000000000000000000000101
//补码:0 00000000000000000000000000000000101
//那么a<<1,由于整数在内存中的存储 —— 二进制的补码,那对a向左移动1位,就是对补码向左移动1位。即:
//a<<1:000000000000000000000000000000001010 ——> 正数的原码二进制也是如此 ——> 10
int c = -1;
int d = c << 1;
printf("%d\\n", d);//打印的是原码
//负数
//比如:c = -1
//原码:1 0000000000000000000000000000001
//反码:1 1111111111111111111111111111110
//补码:1 1111111111111111111111111111111
//那么c<<1,由于整数在内存中的存储 —— 二进制的补码,那对a向左移动1位,就是对补码向左移动1位。即:
//c<<1: 1 1111111111111111111111111111110 ——> 反码 = 补码 - 1
//c<<1反码: 1 1111111111111111111111111111101 ——> 原码 = 反码取反
//c<<1原码: 1 0000000000000000000000000000010 ——> -2
return 0;
}
1.2.2右移运算符>>
右移运算符移位规则:
- 逻辑右移:右边丢弃,左边补0
- 算术右移:右边丢弃,左边补符号位(绝大多数编译器是算术右移)
见右移运算符的代码,注释内容~~~,来深刻理解:
注意:逻辑右移和算术右移的实际区别对比。
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
// >> —— 右移操作符
//逻辑右移:右边丢弃,左边补0
//算术右移:右边丢弃,左边补符号位
// << —— 左移操作符
//
//右移操作符
int a = 5;
int b = a >> 1;
printf("%d\\n", b);
//正数
//比如:对于a = 5来说,是个整数,而整数占4个byte,32个bit位:
//原码:0 00000000000000000000000000000000101
//反码:0 00000000000000000000000000000000101
//补码:0 00000000000000000000000000000000101
//那么a>>1,由于整数在内存中的存储 —— 二进制的补码,那对a向右移动1位,就是对补码向右移动1位。即:
//a>>1:000000000000000000000000000000000010 ——> 正数的原码二进制也是如此 ——> 2
int c = -1;
int d = c >> 1;
printf("%d\\n", d);//打印的是原码
//负数
//比如:c = -1
//原码:1 0000000000000000000000000000001
//反码:1 1111111111111111111111111111110
//补码:1 1111111111111111111111111111111
//那么c>>1,由于整数在内存中的存储 —— 二进制的补码,那对a向右移动1位,就是对补码向右移动1位。即:
//c>>1: 1 1111111111111111111111111111111 ——> 反码 = 补码 - 1
//c>>1反码: 1 1111111111111111111111111111110 ——> 原码 = 反码取反
//c>>1原码: 1 0000000000000000000000000000001 ——> -1
return 0;
}
此处不再画图赘述,具体细节看上述代码!!一定一定注意逻辑右移和算术右移的区别,但是大多是编译器是算术右移。
警告⚠: 对于移位运算符,不要移动负数位,这个是标准未定义的,即:在不同编译器下可能运算结果不同。 例如:
int num = 10;
num>>-1;//error ——> 标准未定义行为
以上是关于05操作符和表达式的主要内容,如果未能解决你的问题,请参考以下文章