算术操作符
+ - * / %
- 除了%操作符外的其他几个操作符可以作用于整数和浮点数
- 对于/操作符如果两个操作数都为整数,执行整数除法。只要出现浮点数除法就是浮点数除法。
- %操作符的两个操作数必须为整数。返回的是整数之后的余数。
移位操作符
- 移位操作符的操作数只能是整数
- 左移操作符 <<
首先得知道移位是移动二进制。整数的二进制表现形式有三种:原码(按一个数的正负直接写出它的二进制表示形式得到的就是原码)反码(原码的符号位不变其他位按位取反)补码(反码加1)。正数的原码反码补码相同。内存中存的是补码的二进制, 屏幕上打印出来的是原码。 所以在参与移位的时候移动的都是补码。
原码(符号位不变其他按位取反)得到反码 反码加1得到补码
补码(符号位不变其他按位取反)得到反码 反码加1得到原码
int main()
{
int a = 10;
int b = a << 1;
//00000000000000000000000000001010
return 0;
}
左边丢弃右边补0 a<<1的结果是移动之后的效果 ,但是a不变
- 右移操作符 >>
- 算术右移 ( 一般见到都是算术右移)
右边丢弃 左边补原来的符号位
- 逻辑右移
右边丢弃左边直接补0
int main()
{
int a = -1;
int b = a >> 1;
printf("%d\n", a);
printf("%d\n", b);
return 0;
}
对于移位操作符 不要移动负数位 (未经定义)
位操作符 (操作数必须是整数)
- 按位与 &
按二进制位于 对应的二进制位有0则为0 两个同时为1才为1
- 按位或 |
按二进制位或 对应的二进制位有1则为1,两个同时为0才为0
- 按位异或 ^
按二进制位异或 相同为0 ,相异为1
举个例子加深一下印象
题目:不能创建临时变量(第三个变量),实现两个数的交换
int main()
{
int a = 10;
int b = 20;
a = a ^ b; //1
b = a ^ b; //2
a = a ^ b; //3
printf(" %d %d", a, b);
return 0;
}
关于异或操作符的一个结论:a^a=0 , 0 ^a =a 而且异或支持交换律 也就是说3 ^ 5 ^3 的结果就是 3 ^ 3 ^ 5 。但是异或也有缺点 : 可读性差 异或只能针对整数的交换 效率也不如使用临时变量的方法
关于上述代码解释: 第二个a ^b 就是 a ^ b ^b ,可以等价于a , 就相当与 b =a 第三个 a ^ b 就是 a ^ b ^ a 。用一下结论就等价于 b , 就相当于 a = b 自然就完成了 不用创建临时变量实现了 a b 的互换。
赋值操作符
复合赋值符
- += -= *= %= >>= <<= &= |= ^=
单目操作符
!( 逻辑反操作符) 、 -(负值) 、 + (正值) 、 & ( 取地址)‘sizeof ( 操作数的类型长度)、~(对一个数的二进制按位取反)、-- (前置、后置–)、++(前置、后置++)、 *(解引用操作符) 、 (类型) (强制类型转换)
sizeof用于数据类型 必须用括号 sizeof(int ) sizeof用于变量 sizeof(var_name) 或者sizeof var_name 都行。带括号的更加普遍 大多数情况下都使用带括号的 这点和函数不同 所以sizeof并不是函数
~是所有位按位取反
int main()
{
int a = 10;
short s = 5;
printf("%d\n", sizeof(s=a+3));
printf("%d\n", s);
return 0;
}
sizeof 内部的表达式是不参与计算的 里面的大小由操作数类型决定
#include <stdio.h>
void test1(int* arr)
{
printf("%d\n", sizeof(arr));//(2)
}
void test2(char* ch)
{
printf("%d\n", sizeof(ch));//(4)
}
int main()
{
int arr[10] = {0};
char ch[10] = {0};
printf("%d\n", sizeof(arr));//(1)
printf("%d\n", sizeof(ch));//(3)
test1(arr);
test2(ch);
return 0;
}
sizeof(arr)计算的是整个整形数组的大小,单位是字节。10 乘4 = 40 。sizeof(ch)计算的是整个字符数组的大小 为10乘1=10。
第二个sizeof (arr) 实参是数组 数组传参本质上是传首元素地址,形参用指针接收,而指针的大小为4个字节(32位平台)第二个sizeof(ch)实参是数组,数组传参本质上是传首元素地址,这里就会有小伙伴会认为char 类型是一个字节 字符指针就为一个字节 ,但是字符指针也是指针 所以大小为4个字节(32位平台)。
- a++ 、++a 、 a–、 --a的使用
#include <stdio.h>
int main()
{
int a = 10;
int b = a++;
printf("%d\n", a);
printf("%d\n", b);
return 0;
}
上面的代码和下面的代码一表达的意思是一样的 a++ 表示先使用在++ 同理a- -也是一样的道理
//代码1#include <stdio.h>
int main()
{
int a = 10;
int b= a ;
a = a + 1;
printf("%d\n", a);
printf("%d\n", b);
return 0;
}
//代码二
#include <stdio.h>
void test(int b)
{
printf("%d\n", b);
}
int main()
{
int a = 10;
test(a++);
printf("%d\n", a);
return 0;
}
不论是前置++还是后置++会带有副作用 会影响自身,也就是会改变原来的值 上代码!
int main()
{
//1
int a = 10;
int b = ++a;//b=11 a=11
//2
int a = 10;
int b = a + 1;//b=11 a=10
return 0;
}
逻辑操作符
- && 逻辑与 (并且)
- || 逻辑或 (或者)
&& 左边为假 右边不计算 || 左边为真,右边不计算
条件操作符
语法
exp1 ? exp2 : exp3
表达式一 为真 表达式二计算 表达式三不计算 结果为表达式二
表达式一为假表达式二不计算 表达式三计算 结果为表达式三
逗号表达式
语法
exp1, exp2, exp3, …expN
从左至右依次执行 ,左边可能会影响右边的结果 最后一个逗号表达式最为整个表达式的结果
隐式类型转换
##截断操作
int main()
{
char a = 3;
char b = 127;
char c = a + b;
printf("%d\n", c);
return 0;
}
字面常量 3 是不能储存进char 变量中 ,3 是个整数 ,整数所占内存空间是32个比特位 而char 所占内存空间为8个比特位 自然需要发生截断 。那这里就有小伙伴问了 有32位,只需要8位 截断哪里?截断的规则:把低位的字节数放置到需要截断储存的变量中
整形提升
整形提升的条件:只有当表达式中出现长度小于int类型的整形值,才需要整形提升,将其转换位int 类型或者 unsigned int类型
整形提升的规则: 对于有符号类型来说 ,整形提升是在高位补变量的符号位; 对于无符号类型的整形变量,直接高位补0就可以了
补充:
char 到底是signed char 还是unsigned char 是取决于编译器的,不过常见的编译器下,char 是signed char
short 默认是signed short
int默认是 signed int
long 默认是signed long
算术转换
那如果大于整形怎么办 ? 算术转换就用来处理这种情况。如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数的转换为另一个操作数的类
型,否则操作就无法进行。下面的层次体系称为寻常算术转换
long double
double
float
unsigned long int
long int
unsigned int
int
只能向上转换
下面讲一下上述代码的具体过程
a b 截断
00000000 00000000 00000000 00000011 --3
截断 留下 00000011
00000000 00000000 00000000 01111111 --127
截断 留下 01111111
分别整形提升
00000000 00000000 00000000 00000011
00000000 00000000 00000000 01111111
相加
00000000000000000000000010000010
截断 留下 10000010
在提升
11111111 11111111 11111111 10000010 (补码)内存中存储的是补码 ,打印在屏幕上的是原码
再进行转换
11111111111111111111111110000001
10000000000000000000000001111110 (原码)
从而得到结果 -126
如果你觉得这篇文章对你有帮助,不妨动动手指给点赞收藏加转发,给鄃鳕一个大大的关注
你们的每一次支持都将转化为我前进的动力!!!