目录
在算术运算符中,+ - * 跟我们数学中的运算是一样的
在这里主要说一下 / 跟 % 这两个操作符
在除法运算中,若除号两边的操作数都为整型,则结果是取商的部分
操作数:指的就是 被除数 与 除数
eg:a/b a和b均为整数,若a
(小数除以大数结果为0)
在两个整数运算中C语言遵从的是(向0取整)法则
所谓向0取整 就是在 数轴上朝向0的方向取整
eg : 10/8=1.25 数学运算
10/8 =1 C语言
因为1.25>0 在取整的时候不会取到整数2 而是取到1 因为1 比2更接近与0
在除法运算中,只要有一个操作数是浮点数,就是浮点数的除法运算
所谓浮点数的除法运算就是,最后的结果是一个浮点数
- #include
-
- int main()
- {
- printf("%d\n",20/10);//结果就是一个是整数
-
- //小数除大数
- printf("%d\n",2/19);//结果为0
-
- printf("%lf\n",20.0/10);//结果是一个浮点数
- printf("lf\n",20.0/10.0);//结果是一个浮点数
- return 0;
- }
在取模运算中 取到的结果是两数相除之后所留的余数
取余运算两边的操作符只能是整数
在模运算中,a%b 当a的值小于b时 结果为a
(小数模大数结果为小数本身)
- #include
- int main()
- {
- //两数进行模运算
- printf("%d\n", 5 % 4); //1
-
- //小数 模 大数 得到的是小数本身
- printf("%d\n", 3 % 4); //3
- printf("%d\n", 2 % 19); //2
- return 0;
- }
移动的时二进制位,因为在内存中数据是以补码的形式存在的,同理 移动的是二进制的补码
左移操作符如何移动:左边丢弃,右边补0
移位操作符不能移动负数位
- #include
- int main()
- {
- //左移操作符 <<
- int a = 10;
- //a 的原码:00000000 00000000 00000000 00001010
- //正数的原码 反码、补码 相同
- int b = a << 1;
- //将a左移一位:00000000 00000000 00000000 00010100
- // 左移一位之后还是一个正数,原、反、补 相同
- // b=20
- printf("%d\n", b);
- }
移动的是二进制位 移动的是二进制位的补码
移位规则:
1、算术右移:右边丢弃左边补符号位(大部分编译器都用)
2、逻辑右移:右边丢弃左边补0
- #include
- int main()
- {
- //0 表示正数,1表示负数
- int a = -10;
- //a原码 : 10000000 00000000 00000000 00001010
- // 反码: 11111111 11111111 11111111 11110101
- // 补码: 11111111 11111111 11111111 11110110
- //将补码算术右移一位
- int b = a >> 1;
- //补码:11111111 11111111 11111111 11111011
- // 10000000 00000000 00000000 00000100
- //原码:10000000 00000000 00000000 00000101
- // b=-(1+4)=-5
- printf("%d\n", b);
- return 0;
- }
& 按位与:操作的是二进制的补码,二进制位一位一位的运算
运算规则:两个对应的二进制位只要有0结果为0,只有全为1时结果为1
(有0为0,全为1为1)
- #include
- int main()
- {
- //&:有0为0 同为1为1
- int a = 10;
- int b = 20;
- int c = a & b;
- printf("%d\n", c);
- //正数的 原码、反码、补码相同
- //a原码:00000000 00000000 00000000 00001010
- //b原码:00000000 00000000 00000000 00010100
- //a&b: 00000000 00000000 00000000 00000000
- //c=0;
- return 0;
- }
| 按位或:操作的是二进制的补码,二进制位对齐运算
运算规则:对应的二进制位 只要有一个 1 结果为 1 ,都为 0 结果为 0
(有1为1 ,同0为0)
- #include
- int main()
- {
- int a = 10;
- int b = 20;
- int c = a | b;
- printf("%d\n", c);
- //正数的原码、反码、补码相同
-
- //a的补码: 00000000 00000000 00000000 00001010
- //b的补码:00000000 00000000 00000000 00010100
- // a | b: 00000000 00000000 00000000 00011110
- //c=2+4+8+16=30
- return 0;
- }
^ 按位异或:操作的是二进制位的补码,二进制位对齐运算
运算规则:二进制位相同为 0 ,二进制位不同为 1
(相同为0,相异为1)
任何数和0异或,结果都是任何数本身
任何数异或其本身 结果都是0
- #include
- int main()
- {
- int a = 0;
- int b = 10;
- int c = a ^ b;
- printf("%d\n", c);
-
- //正数的原码、反码、补码 相同
-
- //a 补码:00000000 00000000 00000000 00000000
- //b 补码:00000000 00000000 00000000 00001010
- //c 补码:00000000 00000000 00000000 00001010
- //c是正数,原码、反码、补码 相同
- //c=10
-
- //总结:任何数 和 0 异或 结果都是其本身
- return 0;
- }
- #include
- int mian()
- {
- //不使用第三方变量,交换值
- int a = 10;
- int b = 0;
- a = a ^ b;
- b = a ^ b;
- a = a ^ b;
-
- //用等量代换方法
- // a=a^b;
- // b=a^b^b; b^b=0 ==> b=a
- // a=a^b^a a^a=0 ==> a=b
- //按位异或具有结合律
- return 0;
- }
~ 按位取反:操作的是二进制位的补码
运算规则:将二进制位的 0变成1 ,1变成0
- #include
- int main()
- {
- int a = -1;
- int b = ~a;
- printf("%d\n", b);
- //a:
- //原码:10000000 00000000 00000000 00000001
- //反码:11111111 11111111 11111111 11111110
- //补码:11111111 11111111 11111111 11111111
-
- // ~a: 00000000 00000000 00000000 00000000
- //~a 符号位是0 是正数,正数的原 反 补 相同
- // ~a 原码 :00000000 00000000 00000000 00000000
- // b=0;
- return 0;
- }
就是给一个变量赋值
- #include
- int main()
- {
- // +=
- int a = 100;
- a += 11; //a=a+11 a=111
- printf("%d\n", a);
-
- // -=
- int b = 90;
- b -= 20; //b=b-20 //b=70
- printf("%d\n", b);
-
- // *=
- int c = 10;
- c *= 2; // c=c*2 c=20
- printf("%d\n", c);
-
- // /=(除等于)
- int d = 30;
- d /= 10; // d=d/10 d=3
- printf("%d\n", d);
-
- // %=
- int e = 120;
- e %= 6; // e=e%6 e=0
- printf("%d\n", e);
- }
- #include
- int main()
- {
- // <<=
- int a = 10;
- a <<= 2; // a=a<<2 a=40
- //a 补码: 00000000 00000000 00000000 00001010
- //a<<2 : 00000000 00000000 00000000 00101000
- printf("%d\n", a);
-
- // >>=
- int b = 20;
- b >>= 2; // b=b>>2 b=5
- //b补码:00000000 00000000 00000000 00010100
- //b>>2 :00000000 00000000 00000000 00000101
- printf("%d\n", b);
- return 0;
- }
- int main()
- {
- // &=
- int a = 10;
- a &= 2; // a=a&2 a=2
- printf("%d\n", a);
-
- // a补码:00000000 00000000 00000000 00001010
- // 2补码:00000000 00000000 00000000 00000010
- // a & 2:00000000 00000000 00000000 00000010
- // &(按位与):有0为0 同1为1
-
-
- // |=
- int b = 20;
- b |= 12; // b=b | 12 b=28
- printf("%d\n", b);
-
- // | (按位或) :有1为1,同0为0
- // b补码:00000000 00000000 00000000 00010100
- //12补码:00000000 00000000 00000000 00001100
- //b | 12:00000000 00000000 00000000 00011100
-
-
- // ^=
- int c = 30;
- c ^= 16; // c=c^16 c=14
- printf("%d\n", c);
-
- // ^ 相同为0 相异为1
- // c补码:00000000 00000000 00000000 00011110
- //16补码:00000000 00000000 00000000 00010000
- //c ^ 16:00000000 00000000 00000000 00001110
- return 0;
- }
操作数只有一个的操作符号
sizeof 操作符 是一个操作符,要区分它与函数
sizeof 主要用于计算数据类型在内存中的大小(单位是字节)
在计算变量的大小的时候sizeof的括号可以省略
- #include
-
- int main()
- {
- // ! 逻辑反
- if (!1)
- printf("!1为真\n");
- else
- printf("!1为假\n");
-
- // - 、+ 号
- int a = -10;
- a=-a;
- printf("%d\n", a);
-
- int b = 20;
- b = +b;
- printf("%d\n", b);
-
- // & 取地址
- int c = 30;
- printf("%p\n", &c);
-
- // sizeof操作符
- int d = 40;
- printf("%d\n", sizeof(d));
- printf("%d\n", sizeof (int));//类型的括号不能省略
- printf("%d\n", sizeof d);//括号可以省略
-
- // ~ 按位取反 只能运算与整数
- int e = 50;
- printf("%d\n", e);//未操作前
- int f = ~e;// 对e 按位取反 赋值给f
- //f=-(1+2+16+32) f=-51
- printf("%d\n", f);
- // e补码:00000000 00000000 00000000 00110010
- //~e补码:11111111 11111111 11111111 11001101
- // :10000000 00000000 00000000 00110010
- //~e原码:10000000 00000000 00000000 00110011
-
- return 0;
- }
sizeof(数组名):表示整个数组在内存中所占空间的大小 单位是字节
sizeof 在计算数组大小 的时候 在函数内跟函数外是有区别的
- #include
-
- void MAX(int arr[])
- {
- int b = sizeof(arr);
- // 在32位下是4 在64位下是8
- printf("%d\n", b);
-
- //因为数组在传参的时候传的是数组名,数组名是首元素地址
- //所以在传参的时候传的是指针
- // 函数里面得用指针来接受,我们只是将形参写成了数组的形式,但其本质上是一个指针
- //指针在32位下占4个字节,在64位下占个字节
- }
- int main()
- {
- int arr[5] = { 1,2,3,4,5 };
- //计算整个数组的大小
- int a = sizeof(arr);
- printf("%d\n", a);
-
- //调用函数 函数实参是数组名
- MAX(arr);
- return 0;
- }
前置--:先--,后使用 (先让变量自减1,再使用)
后置--:先使用,后-- (先使用,再让变量自减1)
- #include
- int main()
- {
- //前置--
- int a = 10;
- int b = --a;
- //此代码执行了两部操作
- // 第一步:a=a-1;
- // 第二步:b=a;
- printf("%d\n", b);//b的值为9
-
- //后置--
- int c = 20;
- int d = c--;
- //此代码也执行了两步操作
- // 第一步:d=c;
- // 第二步:c=c-1;
- printf("%d\n", d);//d的值为20
- return 0;
- }
前置++:先++后使用(先让变量自增1,再使用)
后置++:先使用后++(先使用,再让变量自增1)
- #include
- int main()
- {
- //前置++
- int a = 10;
- int b = ++a;
- //分为两步
- // a=a+1;
- // b=a;
- // 先让a自增1 再使用a 把a的值赋给b
- printf("%d\n", b);//b的值为11
-
- //后置++
- int c = 20;
- int d = c++;
- //分为两步
- // d=c;
- // c=c+1;
- //先使用c 把c的值赋给d 再让c自增1
- printf("%d\n", d);//d的值为20
- return 0;
- }
解引用操作符,也被叫做间接访问操作符,运用于指针
作用:将指针变量进行解引用操作,就是取到指针变量所指向的内容
- #include
- int main()
- {
- int a = 10;
-
- //定义一个整型指针变量,里面存放的是整型变量a的地址
- int* p = &a;
-
- //我们将指针变量解引用操作
- // 取到的是指针变量p所指向的内容 也就是a
- printf("%d\n", *p);// 10
-
- //同理:*p 其实就是 a
- //也可给其赋值
- *p = 20;
-
- //此时a的值被赋值成20
- printf("%d\n", a);// 20
- return 0;
- }
强制类型转换就是将一种类型的数据,强制转换成另一种类型的数据
注意:当大类型往小类型转换时会发生截断
当 float 或者 dauble 类型强转为 int 类型时: 发生截断 取到的是整数部分
当 char 类型 强转为 int 类型时:取到的是其对于的 ACSII码值
- #include
- #include
-
- int main()
- {
- // float 转 int 截断取整数部分
- float a = 3.14f;
- int b = (int)a;
- printf("%d\n", b);// b为3
-
- // double 转 int 截断取整数部分
- double d = 4.225;
- int e = (int)d;
- printf("%d\n", e);// e为4
-
- // char 转 int 取到ASCLL值
- char c = 'A';
- int f = (int)c;
- printf("%d\n", f);// f 为 65
-
- //动态内存开辟
- // 将在堆区上开辟的空间强制转化为int* 类型 赋给 指针p
- int* p = (int*)malloc(sizeof(int)* 13);
-
- //时间戳产生随机数
- //将time 函数的返回值强制转化成 unsinged int (无符号整型)
- // srand 函数的参数是一个无符号整型所以强制类型转换
- srand((unsigned int)time(NULL));
- int x = rand();//产生一个 0 - 32767 的随机数
- printf("%d\n", x);//每次打印出现的结果都不一样
-
- return 0;
- }
跟数学中的判断一样,
不过在这里多了一个 != (不等于):判断两个数是否不相等
- #include
- int main()
- {
- int a = 10;
- int b = 20;
- if (a > b)
- {
- printf("a>b\n");
- }
- if (a < b)
- {
- printf("a);
- }
- if (a == b)
- {
- printf("a==b\n");
- }
- if (a != b)
- {
- printf("a!=b\n");
- }
-
- int c = 20;
- int d = 30;
- if (c >= d)
- {
- printf("c>=d\n");
- }
- if (c <= d)
- {
- printf("c<=d\n");
- }
- return 0;
- }
&& 并且操作符:只要一个条件为假,结果就为假,全部为真结果才为真
短路现象:当我们 && 多个条件时:若第一个条件为假,则结果直接为假,后面的条件不会对其进行判断(也就是只要遇到假条件,后面的所有条件都不会被判断)
- #include
-
- int main()
- {
- // 输入一个年份
- //判断是否 能被4整除 并且 不能被100整除
- //若能 打印出这个年份
- int year = 0;
- scanf("%d", &year);
-
- if ((year % 4 == 0) && (year % 100 != 0))
- {
- printf("此年份为:%d\n",year);
- }
- else
- {
- printf("%d 年份 (能被4整除并且不能被100整除)不成立\n", year);
- }
- return 0;
- }
|| 或者操作符: 只要有一个条件为真结果就为真,全都为假 结果才为假
短路现象:当我们判断的条件只要遇到条件为真,后面的条件就不判断
- #include
-
- int main()
- {
- //判断闰年
- //能被4整除并且不能被100整除,或者能被400整除的年份是闰年
- int year = 0;
- scanf("%d", &year);
-
- if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0))
- {
- printf("%d 年 是闰年\n",year);
- }
- else
- {
- printf("%d 年 不是闰年\n",year);
- }
-
- return 0;
- }
! 逻辑反操作符
让真变为假,假变为真
- #include
- int main()
- {
- // 在C语言中数字 0 表示假,非0数字表示真
- int a = 10;
- if (!a)
- {
- printf("!a 为真\n");
- }
- else
- {
- printf("!a 为假\n");
- }
- return 0;
- }
表达式1 ?表示式2 :表达式3 ;
条件操作符,又叫三目运算符,因为有三个操作数
当表达式1 为真执行表达式2 ,否则执行表达式3
- #include
-
- int main()
- {
- //输入两个数打印两个数中的较大值
- int a = 0;
- int b = 0;
- scanf("%d %d", &a, &b);
-
- int max = (a > b ? a : b);
- printf("%d\n", max);
-
- //a > b ? printf("%d\n", a) : printf("%d\n", b);
- return 0;
- }
逗号表达式就是用逗号隔开多个表达式
逗号表达式从左向右依次执行
逗号表达式的结果就是最后一个表达式
- #include
- int main()
- {
- int a = 10;
- int b = 20;
- int c = 30;
-
- //d的结果就是逗号表达式中最后一个表达式的结果
- //也就是将c的值赋给d
- int d = (a, b, c);
- printf("%d\n", d); // d为30
- }
[] 下标引用操作符 ,以索引的方式操作数组
[下标数]
- #include
- int main()
- {
- int arr[5] = { 1,2,3,4,5 };
- //下标引用
- arr[0] = 8;
- //打印数组
- int i = 0;
- for (i = 0; i < 5; i++)
- {
- printf("%d ", arr[i]);
- }
- return 0;
- }
函数名():进行函数调用
()里面可以有参数,也可以没有参数
函数调用操作符,至少有一个操作数,函数名也是它的操作数,其余操作数就是所传的参数
- #include
- void Print(int a)
- {
- printf("%d\n", a);
- }
-
- int main()
- {
- int a = 10;
- Print(a);//() 有两个操作数 函数名和a
- return 0;
- }
结构体变量 . 成员变量
用结构体变量访问结构体成员
- #include
-
- //创建结构体
- struct SS {
- char name[10];
- int age;
- };
-
- int main()
- {
- //创建结构体变量并初始化
- struct SS s1 = { "张三",18 };
-
- //访问结构体成员(结构体变量 . 成员变量)
- printf("名字:%s 年龄:%d\n", s1.name, s1.age);
- }
结构体指针->结构体成员变量
用结构体指针访问成员
- #include
-
- //创建结构体
- struct SS {
- char name[10];
- int age;
- };
-
- int main()
- {
- //创建结构体变量并初始化
- struct SS s1 = { "张三",18 };
-
- //创建结构体指针变量 让其指向s1
- struct SS* p = &s1;
-
- // 用结构体指针访问成员(->)
- printf("名字:%s 年龄:%d\n", p->name, p->age);
- }
在C语言中,当小于int 类型的 其它类型在计算的时候会将其 转化成int 类型进行计算
最后在进行截断赋给接收值的类型,若是int 则不截断
在整型提升过程中 不足整型的类型数 :
无符号数二进制位前面补0,有符号数二进制位前面补1 补够一个int 类型大小即可
- #include
-
- int main()
- {
- short a = 10; //在内存中占两个字节
- //二进制表示:00000000 00001010
-
- char b = 1;//在内存中占一个字节
- //二进制表示:00000001
-
- short c = a + b;
- //在计算的时候进行整型提升在计算
- // 无符号数前面补0,有符号数补符号位
-
- // a提升:00000000 00000000 00000000 00001010
- // b提升:00000000 00000000 00000000 00000001
- // a+b :00000000 00000000 00000000 00001011
-
- //放进c中的时候因为c是short类型所以要发生截断
- // c : 00000000 00001011
- // c=11
- printf("%d\n", c);
- return 0;
- }
在进行计算时:如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数的转换为另一个操作数的类型 这就是算术转换
long double
double
float
unsigned long int
long int
unsigned int
int
自下而上,进行算术转换
- #include
-
- int main()
- {
- int a = 3;
- double b = 3.14;
- double c = a + b;
- //此时会将整型变量a 算术转换成 double 类型 进行计算
- printf("%lf\n", c);
- return 0;
- }
多个相邻操作符混合计算时,我们就得考虑操作符的优先级
优先级高的先计算
有些操作符是具有结合性的既遵从从左向右计算,也遵从特殊的两个先结合计算
有些操作符是控制求值顺序的
像,逗号表达式、三目运算符、逻辑与、逻辑或,都是控制求值顺序的,从左向右依次执行