一、算数操作符
+ 加 - 减 * 乘 / 除 % 取余
//算术操作符:+ - * / %
int a = 7;
int b = 4;
int sum1 = a + b;//加法运算符,结果为11
int sum2 = a - b;//减法运算符,结果为3
int sum3 = a * b;//乘法运算符,结果为28
int sum4 = a / b;//除法法运算符,结果为1
int sum5 = a % b;//取模(取余)运算符,结果为3
注意以下几点:
1.在c语言中乘法是使用*这个符号,并不是x这个。
2.在除法运算中,想要得到小数点后的数字应该是这样的。
float a = 7 / 4;//打印结果1.000000(float类型保留7位数字)
//那为什么a是浮点型但输出并不是精准的小数呢?
//在c语言中规定要得到精确的小数应该在除数或者被除数的整型后后面加 .0
//有且仅有一个加 .0就可义
float b = 7 / 4.0;//打印结果1.750000
float b = 7.0 / 4.;//打印结果1.750000
float b = 7.0 / 4.0;//打印结果1.750000
printf("%f\n", a);
printf("%f", b);
3.在取模运算中
a.得到的结果是两个数相除之后所留下的数。
b.操作符的两边只能是整数。
c.a%b 当a的值小于b时得到的结果为a(小数模大数的结果为小数本身)。
二、位移操作符
<< 左移 >> 右移
移动的是二进制位,因为内存中的数据是以补码的形式存在的,所以同理移动的是二进制的补码。
//左移操作符 <<
int a = 10;
//a的原码:00000000 00000000 00000000 00001010
//正数的原码、反码、补码都是相同的
int b = a << 1;//将a左移一位之后赋值给b
//a左移后:00000000 00000000 00000000 00010100
//左移后还是正数所以原码、反码、补码都是相同的
//b = 20
printf("%d\n", b);
//右移操作符 >>
int a = -10;//在原码中的左边第一位表示正负,0表示正数,1表示负数
//a的原码:10000000 00000000 00000000 00001010
//a的反码:11111111 11111111 11111111 11110101
//a的补码:11111111 11111111 11111111 11110110
int b = a >> 1;
//b的补码:11111111 11111111 11111111 11111011
//b的反码:11111111 11111111 11111111 11111010
//b的原码:10000000 00000000 00000000 00000101
//b=-(1+4)=-5
printf("%d\n", b);
注意:
1.正数的原码、反码、补码都是一样的。
2.第一位是符号位,所以0表示正数,1表示负数。
3.在右移操作符中分了两种:算数位移和逻辑位移。
a.算数位移:丢弃右边,补符号位。
b.逻辑位移:丢弃右边,左边的符号位直接补0(不论正负)。
三、位操作符
& 按位与 | 按位或 ^ 按位异或
// 按位与&(相同时留下,不相同时取0)
int a = 1;
int b = 10;
//a的原码:00000000 00000000 00000000 00000001
//b的原码:00000000 00000000 00000000 00001010
//a&b : 00000000 00000000 00000000 00000000
int c = a & b;
printf("%d\n", c);//打印结果为0
// 按位或 | (有1为1,无1为0)
int a = 1;
int b = 10;
//a的原码:00000000 00000000 00000000 00000001
//b的原码:00000000 00000000 00000000 00001010
//a|b : 00000000 00000000 00000000 00001011
int c = a | b;
printf("%d\n", c);//打印结果为11
// 按位异或 ^ (相同为0,相异为1)
int a = 1;
int b = 10;
//a的原码:00000000 00000000 00000000 00000001
//b的原码:00000000 00000000 00000000 00001010
//a^b : 00000000 00000000 00000000 00001011
int c = a ^ b;
printf("%d\n", c);//打印结果为11
return 0;
四、赋值操作符
= += -= *= /= ^= |= >>= <<=
//赋值操作符
// =
int a = 10;//将a初始化
a = 1;//将1赋值给a,此时a的值为1
// +=
a += 1;//与a=a+1一样
// -=
a -= 1;//与a=a-1一样
// *=
a *= 2;//与a=a*2一样
// /=
a /= 5;//与a=a/2一样
// &=
a &= 3;//与a=a&3一样
// ^=
a ^= 3;//与a=a^3一样
// |=
a |= 1;//与a=a|3一样
// >>=
a >>= 1;//与a=a>>1一样
// <<=
a <<= 1;//与a=a<<1一样
//右移操作和左移操作可以看前面的讲解
五、单目操作符
! - + & sizeof ~ -- ++ * (类型)
// ! 逻辑反操作
int a = 5;
//在c语言中,0为假,非0为真
if (a)//此时a为5,为真,执行下面语句
{
printf("haha\n");
}
if (!a)//因为a非0,所以为真,逻辑取反!a就为假
{
printf("hehe\n");
}
//所以最后打印的是hehe
// sizeof 操作数的类型长度(以字节为单位)
printf("%d\n",sizeof(int));//4字节
printf("%d\n", sizeof(char));//1字节
printf("%d\n", sizeof(short));//2字节
printf("%d\n", sizeof(long));//4字节
printf("%d\n", sizeof(float));//4字节
printf("%d\n", sizeof(double));//8字节
//利用sizeof求出了各种数据类型的长度
// ~ 对一个数的二进制按位取反
int a = -1;
int b = 1;
//a的原码:10000000 00000000 00000000 00000001
//a的反码:11111111 11111111 11111111 11111110
//a的补码:11111111 11111111 11111111 11111111
//~a的补码:000000000 00000000 00000000 00000000
//a的符号位为0,所以原码、反码、补码都相同
b = ~a;
printf("%d\n", b);//打印的结果为0
int main()
{
int a = 0;
printf("%d", &a);//&取地址符,取出a对应内存空间的地址。
return 0;
}
int main()
{
int a = 10;
int b = a++;//先使用,后加加
//b=a a=a+1
printf("%d\n", b);//结果为10
printf("%d\n", a);//结果为11
int a = 10;
int b = ++a;//先加加,后使用
//a=a+1 b=a
printf("%d\n", b);//结果为11
printf("%d\n", a);//结果为11
int a = 10;
int b = a--;//先使用,后减减
//b=a a=a-1
printf("%d\n", b);//结果为10
printf("%d\n", a);//结果为9
int a = 10;
int b = --a;//先减减,后使用
//a=a-1 b=a
printf("%d\n", b);//结果为9
printf("%d\n", a);//结果为9
return 0;
}
int main()
{
int a = 1;
int* pa = &a;//创建一个变量指针pa,将a的地址初始化给pa
*pa = 5;//使用解引用操作符,将5赋值给指针pa所指向的空间内存
//*pa = 5 和 a = 5 一样
printf("%d",a);//结果为5
return 0;
}
int main()
{
int a =(int)3.14;//这里3.14是一个浮点数但是a是一个整型
//所以这里强制转换类型为整型
printf("%d", a);//打印结果为3
return 0;
}
六、逻辑操作符
&& 逻辑与 || 逻辑或
// &&逻辑与
int a = 1;
int b = 1;
scanf_s("%d %d", &a,&b);
if (a >= 18 && a <= 36)//当a>=18和a<=36同时成立时,if条件为真
printf("haha\n");
// ||逻辑或
if (b <= 18 || b >= 36)//当a>=18和a<=36有一个成立时,if条件为真
printf("hehe");
下面有个例子:
int main()
{
int i = 0;
int a = 0;
int b = 2;
int c = 3;
int d = 4;
i = a++ && ++b && d++;//这里打印的结果是什么呢?
//首先我们分析a++ 先a=0后a=a+1
//所以i=0 && ++b && d++
//因为逻辑与的左边等于0了,所以右边就不用计算了 i= 0 && d++
//所以后面的 ++b d++ 是不用执行的
printf("%d %d %d %d", a,b,c,d);//打印结果1,2,3,4
return 0;
}
int i = 0;
int a = 1;
int b = 2;
int c = 3;
int d = 4;
i = a++ || ++b || d++;//这里打印的结果是什么呢?
//首先我们分析a++ 先a=0后a=a+1
//所以i=1 || ++b || d++
//因为逻辑或左边为真的话,右边的就不用计算了
// 所以 ++b d++ 都会执行
printf("%d %d %d %d", a, b, c, d);//打印结果2,3,3,5
注意:
1.逻辑与(&&):在左边的表达式为假时,右边的表达式就不进行计算。
2.逻辑或( || ):在左边的表达式为真时,右边的表达式就不进行计算。
七、条件操作符
( exp1 ?exp2 :exp3 )三目操作符
int main()
{
int a = 2;
int b = 3;
int c = 0;
//( exp1 ? exp2 : esp3 )
c = (a > b ? a : b);
//当表达式1为真时,计算表达式2,不计算表达式3,并将表达式2的结果返回
//当表达式1为假时,不计算表达式2,计算表达式3,并将表达式3的结果返回
printf("%d", c);//打印结果为3
return 0;
}
八、逗号表达式
exp1,exp2,exp3,exp4,exp5,exp6..........expN
逗号表达式,从左向右依次执行。整个表达式的结果是最后一个表达式的结果。
int main()
{
int a = 1;
int b = 2;
int c = (a > b, a = b + 10, a, b = a + 1);
//因为逗号表达式的结果是最后一个表达式的结果
// 所以我们可以先看最后一个表达式,然后在看前面的表达式有没有影响最后一个表达式的
//a>b 比大小,不影响最后表达式可以不看省略
//a=b+10 此时a=10
//a a值不变
//b=a+1 b=12+1=13
printf("%d", c);//打印结果为13
return 0;
}
附加:整型提升
首先,我们看下面的代码以及输出结果:
看到上面这段代码,c=a+b,这里c是整型,可a,b是字符型,为什么可以相加呢?
这里我们就要介绍我们经常忽略的整型提升:
int main()
{
char a = -1;
//一个字符型的大小是一个字节也就是8bit
//所以a=-1换算成二进制就是
//100000001 原码
//111111110 反码
//111111111 补码
//因为char是有符号整型,所以在整型提升中高位补符号位即1
//11111111 11111111 11111111 11111111
//这个就是整型提升,提升到4个字节
char b = 1;
//000000001 原码=反码=补码
//因为char是有符号整型,所以在整型提升中高位补符号位即0
//00000000 00000000 00000000 00000001
//这个就是整型提升,提升到4个字节
int c = 0;
c = a + b;//11111111 11111111 11111111 11111111 + 00000000 00000000 00000000 00000001
//二进制运算结果为 00000000 00000000 00000000 00000000
//即0
printf("%d", c);//0
return 0;
}
将a和b的类型的大小提升到int类型的大小再进行相加。
注意:有符号整型在高位就补符号位,无符号整型高位补0。