运算符是什么,分哪些类?
运算符是具有一定运算规则的符号
分类:
1、赋值运算符 =
2、算术运算符 + - * / %
3、关系运算符 > >= < <= == !=
4、逻辑运算符 && || !
5、其他运算符 ++ -- ?:
6、复合运算符 += -= *= /= %= &= |= ^= <<= >>
7、位运算符 & | ^ ~ << >>
运算符相关的概念:
运算符:具有一定运算规则的符号
运算符处理的对象:表达式
表达式具有确定结果的式子:常量-5 a a+5
C语言非0即为真,0为假。数值为0都为假 假:'\0'、NULL等
运算符
1、赋值运算符
内存空间进行赋值操作
内存空间 = 表达式
注意:
原则上来说赋值运算符左右两侧的类型要一直,如果不一致会发生自动转换,转不了会报错和出现警告
可以使用类型强制转换来解决 赋值符号 两侧类型不一致的问题。
强转格式:(类型)值;
int a = 34.5; //输出为34
char ch;
int *p = &ch; //[Warning] initialization from incompatible pointer type
以上都是因为=左右两边类型不同导致问题
可以使用类型强制转换来解决 赋值符号 两侧类型不一致的问题。
强转格式:(类型)值;
int a = (int)34.5;
char ch;
int *p = (int *)&ch;
2、算术运算符
/:
如果两边都是整数结果是整数
如果有一个数是小数结果就是小数
10/3==3
10.0/3==3.333333
x,y是double类型,x=1,y=x+3/2=2.0
%:取余数
取余数
注意事项:两边必须都要是整数
10 % 3 == 1
57 % 3 == 0
对于%取余的总结
m % n的可能结果 0 ~ n-1
m % n == 0,m和n的关系:m能被n整除 m是n的倍数 n是m的因数
m % n !=0,m和n的关系:m不能被n整除 m不是n的倍数 n不是m的因数
整除不是用 / 而是用 % 看结果是否为0
//输入一个数据,判断它是偶数还是奇数
/*
偶数:能被2整除的数
奇数:不能被2整除
思路:
定义一个变量
提示输入一个数据
scanf接收数据
如果 数据 % 2 == 0成立,就证明 数据是偶数
否则 数据就是奇数
*/
#include<stdio.h>
int main(void)
{
int a;
printf("请输入一个数");
scanf("%d",&a);
if(a % 2 == 0)
{
printf("这是个偶数");
}
else
{
printf("这是个奇数");
}
}
%应用:数据分离
十进制数据的分离:
3456 分离出它的个位 十位 百位 千位
思路1:
从原数据中将想要获取的数字放在最高位
千位:3456 / 1000 == 3
百位:3456 % 1000 == 456 / 100 == 4
十位:3456 % 100 == 56 / 10 == 5
个位:3456 % 10 == 6
如果输入的数过于大超过了千位,可以在取千位那一步加上%10来保证代码的严谨性。3456 / 1000 % 10
思路2:
从源数据中将想要获取的数字放在个位上
个位:3456 % 10 == 6
十位:3456 / 100 == 56 % 10 == 5
百位:3456 / 1000 == 456 % 100 == 4
千位:3456 / 1000 % 10 == 3
//输入一个16进制的数据,输出分离它的每一位
#include <stdio.h>
int main(void)
{
int a,ge,shi,bai,qian;
printf("请输入一个十六进制数:");
scanf("%x",&a);
qian = a / (16*16*16) % 16;
bai = a % (16*16*16) / (16*16);
shi = a % (16*16) / 16;
ge = a % 16;
printf("你输出的这个数的个位:%x,十位:%x,百位:%x,千位:%x\r\n",ge,shi,bai,qian);
}
//输入一个四位数,输出它每一位上的数字
#include <stdio.h>
int main(void)
{
int a,ge,shi,bai,qian;
printf("请输入一个四位数:");
scanf("%d",&a);
qian = a / 1000 % 10;
bai = a % 1000 / 100;
shi = a % 100 / 10;
ge = a % 10;
printf("你输出的这个数的个位:%d,十位:%d,百位:%d,千位:%d\r\n",ge,shi,bai,qian);
}
3、关系运算符
> >= < <= ==(等于,关系比较) !=(不等于)
关系成立或者不成立,成立为真 --- 1;不成立则为假 --- 0;
0 == '\0' --- 成立
0 == '0' --- 不成立 ‘0’ == 48
表达:
m能被n整除: m % n == 0
m不能被n整除:m % n != 0
4、逻辑运算符
&&:逻辑与
格式:
表达式1 && 表达式2
规则:
全真为真,有假则假(若第一个表达式为真,则整体表达式为真,后续表达式内数值不变)
表达式1
表达式2
表达式1&&表达式2
真
真
真
真
假
假
假
---
假
应用:
一般表示 同时 并且
举例:
如三位数 100 ~ 999 ---> n >=100 && n<=999;
小写字母'a' ~ 'z' ---> ch >= 'a' && ch <= 'z';
大写字母'A' ~ 'Z' ---> ch >= 'A' && ch <= 'Z';
数字字符'0' ~ '9' ---> ch >= '0' && ch <= '9';
//求三个数中最大值:
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
if(a > b && a > c)
{
printf("最大值是:%d",a);//最大值是a
}
if(b > a && b > c)
{
printf("最大值是:%d",b);//最大值是b
}
if(c > a && c > b)
{
printf("最大值是:%d",c);//最大值是c
}
||:逻辑或
格式:
表达式1 || 表达式2
规则:
有真为真,全假为假(若是第一个表达式为真,则整体表达式为真
表达式1
表达式2
表达式1||表达式2
真
---
真
假
真
真
假
假
假
应用:
表达 或者
n不是三位数的表达式: n < 100 || n > 999
ch是字母 (n>='a' && n<='z') || (n>='A' && n<='Z')
!:逻辑非
格式:
!表达式1
规则:
真变假,假变真
表达式1
!表达式1
真
假
假
真
5、其他运算符
++ --:自增1、自减1
1、单独语句使用:
++ 在前和 ++ 在后没有区别
2、作为计算表达式的一部分:
++ 在前先加后用, ++ 在后先用后加
对于第一种: int a = 5; int b = 5; a++; //a = a + 1;//a = 6 ++b; //b = b + 1;//b = 6 printf("%d %d",a,b);//6,6 对于第二种: int a = 5; int b = 5; int c = a++;// 先用a当前的值作为(a++)表达式的结果,结果是5,c=5; //a=a+1; = = 6 int d = ++b;//b = b + 1 = 6 (++b)表达式的结果是6 d=6 printf("%d %d",c,d); //5 6 printf("%d %d",a,b);//6 6
?: :三目运算
格式:
表达式1 ? 表达式2 : 表达式3
规则:
先计算表达式1的结果,如果为真,三目运算符的结果就是 表达式2的效果
如果为假,三目运算符的结果就是 表达式3的结果
//输入两个数据,输出这两个数据中的最大值。
#include <stdio.h>
int main(void)
{
int a,b;
int res;
printf("请输入两个数:");
scanf("%d %d",&a,&b);
printf("你输入的两个数是:a=%d b=%d\r\n",a,b);
res = a > b ? a : b;
printf("最大的数是:%d\r\n",res);
}
unsigned int a = 6;
int b = -10;
a+b > 0 ? printf("yes") : printf("no");
//答案 输出yes
//因为int和unsigned int进行运算时会将int型数据看成unsigned int的数据。
//int b = -10
//1000 0000 0000 0000 0000 0000 0000 1010 ---原码
//1111 1111 1111 1111 1111 1111 1111 0101 ---反码
//1111 1111 1111 1111 1111 1111 1111 0110 ---补码 ---若是看成unsigned int这会是个很大的正数
6、复合运算符
算数+赋值
位运算+赋值
+= -= *= /= %=
&= |= ^= <<= >>=
int a = 3;
a += 2;//--> a = a + 2;
如果实现一个变量自增1的操作:a = a + 1; a++; ++a; a+=1;
逗号运算符
规则:
从左往右计算,最后一个表达式的结果作为','运算符的结果。
int a = 3;
int b = 1;
int c = (a+b,a,b-4); // c = -3;
int d = a+b,a; // d = 4;
7、位运算符
一般将数据转成二进制补码形式
规则:将某位置0还是置1,从地位作为第0位开始数
& | ^ ~ << >>
&:按位与
格式:
数据1 & 数据2
规则:
全1为1,有0则0
将数据转为二进制补码,地位对其(对不齐时高位补零)
|:按位或
格式:
数据1 | 数据2
规则:
有1则1,全0为0
<< :按位左移
格式:
数据 << 移动的位数
规则:
数据整体左移,低位补0,高位溢出舍弃
>>:按位右移
/*
1、截取数据的某一个部分
unsigned int a = 0x12345678;
获取a中间两个字节的数据:
unsigned short b = a >> 8; //0x00123456;
2、将unsigned int 四个字节数据按照字节进行翻转
思路1:
先把每一个字节里面的数据取出来,然后再合数据
思路2:
先把其他不要的位置置0,要的位置置1,然后再合
unsigned int a = 0x12345678;
获取78:a & 0x000000ffUL == 0x00000078; //(UL后缀:unsigned long 将常量数据看成无符号的数据)
获取56:a & 0x0000ff00UL == 0x00005600;
获取34:a & 0x00ff0000UL == 0x00340000;
获取12:a & 0xff000000UL == 0x12000000;
(a & 0x000000ffUL) << 24 == 0x78000000;
(a & 0x0000ff00UL) << 8 == 0x00560000;
(a & 0x00ff0000UL) >> 8 == 0x00003400;
(a & 0xff000000UL) >> 24 == 0x00000012;
(a & 0x000000ffUL) << 24 | (a & 0x0000ff00UL) << 8 | (a & 0x00ff0000UL) >> 8 | (a & 0xff000000UL) >> 24
*/
printf("%#x",b);
return 0;
}
#include<stdio.h>
int main(void)
{
unsigned int a = 0x12345678;
unsigned int b = (a & 0x000000ffUL) << 24 | (a & 0x0000ff00UL) << 8 | (a & 0x00ff0000UL) >> 8 | (a & 0xff000000UL) >> 24;
~:取反
格式:
~数据
规则:
所有位,0变1,1变0
7 --- 0000 0000 0000 0000 0000 0000 0000 0111
~7 --- 1111 1111 1111 1111 1111 1111 1111 1000
^:按位异或
格式:
数据1 ^ 数据2
规则:
相同为0,不同为1
unsigned int a = 0xffffffff;
a = a ^ (1 << 4); // 0xffffffef;
printf("%x\r\n",a);
a = a ^ (1 << 4);
printf("%x\r\n",a);
a = a ^ (1 << 4);
printf("%x\r\n",a);
优先级问题:
() > 单目 > 双目 > 三目 > 赋值复合 > 逗号
双目:
算术运算符 > 关系运算符 > 逻辑运算符
单目运算符:
只有一个表达式
! ++ --等