目录
一、算术操作符
+ - * / %
(一)/ 除法 - -得到的是商
- 除法操作符的两个操作数都是整数的话,执行的是整数除法
- 除法操作符的两个操作数只要有一个浮点数,执行的是小数除法
(二)% 取模(取余)得到的是余数
- 取模操作符的操作数必须是整数
(三)举例
二、移位操作符(移动的是二进制的位)
- << 左移操作符
- >> 右移操作符
(一)各种进制
2进制数据:0至1的数字组成
8进制数据:0至7的数字组成
10进制数据:0至9的数字组成
16进制数据:0 1 2 3 4 5 6 7 8 9 a b c d e f
(二)原码、反码、补码
- 原码:把一个数按照正负,直接翻译成二进制就是原码
- 反码:原码的符号位不变,其他位按位取反
- 补码:反码+1
- 正整数的原码、反码、补码都是相同的,即原码=反码=补码
- 负整数的原码、反码、补码需要计算
- 整数在内存中存储的是补码(2进制)
1. 举例
(三) 左移
1. 规则
- 左边抛弃、右边补0
2. 举例
(四)右移
- >>算数右移:右边丢弃,左边用原来的符号位填充
- >>逻辑右移:右边丢弃,左边直接用0填充
- 具体采用哪种方法右移,取决于编译器
1. 举例
三、 位操作符
(一) 介绍
- & 按位与
- | 按位或
- ^ 按位异或
- 注:他们的操作数必须是整数
(二)& 按位与
(三)| 按位或
(四) ^ 按位异或
(五) 异或相关规律
1. 注意:异或支持交换律
2. 实现两个数的交换【不能创建临时变量(第三个变量)】
//代码1
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
int a = 4, b = 7;
printf("交换前:a=%d,交换后:b=%d\n", a, b);
a = a + b;
b = a - b;
a = a - b;
printf("交换前:a=%d,交换后:b=%d", a, b);
return 0;
}
//代码2
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
int a = 4, b = 7;
printf("交换前:a=%d,交换后:b=%d\n", a, b);
a = a ^ b;
b = a^b;
a = a^b;
printf("交换后:a=%d,交换后:b=%d", a, b);
return 0;
}
四、赋值操作符
(一) 赋值操作符的结合性(求值顺序)是从右到左
- 例如:a=x=y+3,根据操作符的结合性该表达式相当于a=(x=y+3),也等价于
- x=y+3,a=x
(二) 注意
- 不能认为a和x被赋予相同的值,如果x是一个字符型变量,那么y+3的值会被截去一段,以便容纳于字符类型的变量中,那么a所赋的值就是这个被截断后的值
五、单目操作符
(一) 单目操作符介绍
- ! 逻辑反操作
- - 负值
- + 正值
- & 取地址
- sizeof 操作数的类型长度(以字节为单位)
- ~ 对一个数的二进制按位取反
- -- 前置、后置--
- ++ 前置、后置++
- * 间接访问操作符(解引用操作符)
- (类型) 强制类型转换
(二)sizeof
- sizeof操作符判断它的操作数的类型长度,以字节为单位表示,操作数既可以是个表达式(常常是单个变量),也可以是两边加上括号的类型名
1. 举例
2. 注意
- 因为括号在表达式中总是合法的,判断表达式的长度并不需要对表达式求值,所以sizeof(b=a+1)并没有向b赋任何值
3. sizeof和数组
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
void test1(int arr[])
{
printf("%d\n", sizeof(arr));
}
void test2(char ch[])
{
printf("%d\n", sizeof(ch));
}
int main()
{
int arr[10] = { 0 };
char ch[10] = { 0 };
printf("%d\n", sizeof(arr));//40
printf("%d\n", sizeof(ch));//10
test1(arr);//4
test2(ch);//4
return 0;
}
(三)~按位取反
1. 对0取反
2. 举例
六、关系操作符
- >
- >=
- <
- <=
- != 用于测试“不相等”
- == 用于测试“相等”
七、 逻辑操作符
(一)介绍
- && 逻辑与
- || 逻辑或
(二) 举例
八、表达式求值
(一) 隐式类型转换
- C的整型算术运算总是至少以缺省整型类型的精度来进行的。
- 为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换称为整型提升
- 整型提升的意义:
表达式的整型运算要在CPU的相应运算器件内执行,CPU内整型运算器(ALU)的操作数的字节长度一般就是int的字节长度,同时也是CPU的通用寄存器的长度。
因此,即使两个char类型的相加,在CPU执行时实际上也要先转换为CPU内整型操作数的标准长度。
通用CPU(general-purpose CPU)是难以直接实现两个8比特字节直接相加运算(虽然机器指令中可能有这种字节相加指令)。所以,表达式中各种长度可能小于int长度的整型值,都必须先转换为int或unsigned int,然后才能送入CPU去执行运算。
(二) 如何进行整体提升
1. 负数的整形提升
2. 正数的整形提升
3. 无符号整形提升,高位补0
4. 举例
int main()
{
char a = 0xb6;//0xb6为整型提升存储进a中的数据不再是原来的
short b = 0xb600;//原因同上
int c = 0xb6000000;
if (a == 0xb6)
printf("a");
if (b == 0xb600)
printf("b");
if (c == 0xb6000000)
printf("c");
return 0;
}
原因:c只要参与表达式运算,就会发生整形提升,表达式 +c ,就会发生提升,所以 sizeof(+c) 是4个字
节。表达式 -c 也会发生整形提升,所以 sizeof(-c) 是4个字节,但是 sizeof(c) ,就是1个字节。