操作符
算数操作符
+ - * / %
int a1 = 3 / 5;// 0 商 0 余3
// 如果想得到一个小数 需要 小数 除 小数
float a = 3.0 / 5.0;
printf("%f \n", a); // 0.600000
// % 两端必须是整数 不能是小数
int a = 7 % 3;// 7 除 3 商二 余数 1
printf("%d", a);// 1
移位操作符
<< 左移操作符
>> 右移操作符
int main()
{
int a = 2;
int b = a << 1;
// 把a的二进制位向左移动 一 位
// 00000000 00000000 00000000 00000010
// 00000000 00000000 00000000 00000100
printf("%d", b);
return 0;
}
// ---------------------------------------------------------------------------------
int main()
{
int a = 10;
int b = a >> 1;
// 把a的二进制位向右移动 一 位
// 00000000 00000000 00000000 00001010
// 000000000 00000000 00000000 0000101
printf("%d", b);// 5 a没有发生变化
return 0;
}
// ---------------------------------------------------------------------------------
int main()
{
int a = -1;
// 当前的右移操作符 使用的算数右移 高位补的 1
/*
-1 在内存中,存放的二进制的补码
整数的二进制表示形式有三种。
原码:直接根据数值写出的二进制序列
反码:原码的符号位不变 其它位按位取反
补码:反码+1就是补码
针对与负数的 原码 反码 补码
而对于正整数 原码 反码 补码 相同
原码:10000000 00000000 00000000 00000001
反码:11111111 11111111 11111111 11111110
补码:11111111 11111111 11111111 11111111
如果是算数右移 右边丢弃 左边补原符号位。
11111111 11111111 11111111 11111111
如果是逻辑右移 右边丢弃 左边补 0。
01111111 11111111 11111111 11111111
*/
int b = a >> 1;
printf("%d", b);// -1
return 0;
}
右移操作符:
- 算数右移: 右边丢弃,左边补原符号位
- 逻辑右移: 右边丢弃,左边补 0
正数无论是算数右移,还是逻辑右移,高位都补 0.
位操作符
&:按位与 |:按位或 ^:按位异或
int main()
{
int a = 3;
int b = 5;
// & 按(二进制)位与
// 对位的二进制按位与
// 对位二进制都是 1 按位与 1,
// 对位二进制有一个 0 按位与 0
int c = a & b;
printf("%d", c);// 1
// 00000000 00000000 00000000 00000011
// 00000000 00000000 00000000 00000101
// 00000000 00000000 00000000 00000001
return 0;
}
// ---------------------------------------------------------------------------------
int main()
{
int a = 3;
int b = 5;
// & 按(二进制)位或
// 对位的二进制按位与
// 对位二进制都是 有一个 1 就是 1,
int c = a | b;
printf("%d", c);// 7
// 00000000 00000000 00000000 00000011
// 00000000 00000000 00000000 00000101
// 00000000 00000000 00000000 00000111
return 0;
}
// ---------------------------------------------------------------------------------
任何两个相同的数字异或 一定是 0.
int main()
{
int a = 3;
int b = 5;
// 按(二进制)位异或
// 对应的二进制位 进行 异或
// 相同为 0 相异为 1.
int c = a ^ b;
printf("%d", c);// 6
// 00000000 00000000 00000000 00000011
// 00000000 00000000 00000000 00000101
// 00000000 00000000 00000000 00000110
return 0;
}
二进制小练习
int main()
{
// 求一个整数存储在 二进制内存中 1 的个数
// 100 1110 1011
int a = 1259;
int x = 0; // 统计 1的个数
int o = 32;// 循环32次
while (0 < o)
{
int c = a & 1;// 相同为 1 ,不同为 0
a = a >> 1; // 让 a 的二进制向右移动 高位补 0
if (c == 1)
{
x++;
}
o--;
}
printf("%d", x);// 7 个1
return 0;
}
赋值 复合操作符
= += /= *= -= %= >>= <<= &= |= ^=
int a = 10;
a += 100;
a = a + 100;
// 相同
单目操作符
- 单目操作符只有一个操作数。
!:逻辑反操作, - 负值 , + 正值 , &取地址符 , sizefo() 操作数的类型长度,括号中的表达式不会参与运算(以 byte 为单位)
~ 对一个数的二进制按位取反 , -- 前置,后置 -- ,++ 前置 , 后置++
* 间接访问操作符(解引用操作符) , (类型)强制类型转换
小栗子
int main()
{
int flag = 10;
if (flag)
{
printf("真 \n");
}
if (!flag)// !真变假 假变真
{
printf("哈哈 \n");
}
else
{
printf("假 \n");
}
return 0;
}
// -----------------------------------------------------------------
int main()
{
int a = 10;
printf("%d", sizeof(a));// 4 单位是 byte
printf("%d", sizeof(int));// 4 类型也是一样
// 对于变量名计算大小时 可以不用 ()
// sizeof 是一个操作符 不是函数,函数不能省略 ()
printf("%d", sizeof a);
int arr[10] = { 0 };
printf("%d", sizeof(arr));// 单位 byte
printf("%d", sizeof(int[10]));// 同样计算大小
short x = 5;
int a = 10;
printf("%d", sizeof(x = a + 2));// 2 短整型 x占两个byte
// sizeof 中放的表达式是不参与计算的
// 因为处理sizeof是在编译期间处理的,不会参与运算
printf("%d", x);// 5
return 0;
}
// -----------------------------------------------------------------
int main()
{
int a = -1;
/*
10000000 00000000 00000000 00000001 - 原码
11111111 11111111 11111111 11111110 - 反码
11111111 11111111 11111111 11111111 - 补码
按位取反 ~ 包括符号位全部取反 0 变 1 ,1 变 0
00000000 00000000 00000000 00000000
*/
int c = ~a;// 不会改变 a
printf("%d", c);// 0
return 0;
}
// -----------------------------------------------------------------
int main()
{
int a = 13;
// 把a 的二进制中的第五位置变成 1 ;
a = a | (1 << 4);
// 把 a 的二进制中的位置5变为 0
a = a & ~(1 << 4);
printf("%d", a);// 13
return 0;
}
// -----------------------------------------------------------------
int main()
{
int a = 10;
int b = a++;// 后置++ 先使用 再++
printf("%d \n", a);// 11
printf("%d \n", b);// 10
int c = ++a;// ++前置,先++, 后使用
printf("%d \n", a);// 12
printf("%d \n", c);// 12
return 0;
}
// -----------------------------------------------------------------
int main()
{
int a = 10;
// & 取地址
// %p 打印地址 16进制
printf("%p", &a);
// pa就是来存放地址的 - pa是指针变量
// *pa 解引用 间接访问
int* pa = &a;
*pa = 20;// 把 a 改成 20.
printf("%d", a);// a = 20
return 0;
}
// -----------------------------------------------------------------
int main()
{
int a = (float)3.14;// 类型转换
printf("%d \n", a);// 3
return 0;
}
结构成员访问操作符
- 结构体 ->
int main()
{
struct Book
{
char name[20];
char id[20];
int pre;
};
// 结构体变量名.成员名
struct Book b = { "c++","c191191",16 };
printf("name => %s \n", b.name);
printf("id => %s \n", b.id);
printf("pre => %d \n", b.pre);
// 引用 地址
// 结构体指针 -> 成员名
struct Book* pb = &b;
printf("name => %s \n", pb->name);
printf("id => %s \n", pb->id);
printf("pre => %d \n", pb->pre);
return 0;
}
隐式类型转换
- 整型提升是按照变量的数据类型符号位来提升的。
int main()
{
char a = 3;
char b = 127;
char c = a + b;
// 发现 a , b都是char类型 都没达到一个int的大小
// 这里就会发生整型提升
printf("%d", c);// -126
return 0;
}