1. 算术运算符
% 是算术运算符的重点,一般将某个数值控制在一定范围内,还有数据解析上
/与%在处理数据的时候可以进行提取低字节或者高字节数据比如0x123%10,或者0x123/10,应用场景比如温湿度的截取
// demo1:产生一个随机数,并将此数控制在5的范围内
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(int argc, char const *argv[])
{
// 产生随机因子
srand(time(NULL));
// 产生随机数,控制在15以内
int ret = rand() % 15;
printf("%d\n",ret);
return 0;
}
注意点:
减号也是负号,比如-a是取变量a的相反数
取模运算要求左右两边操作数必须是整型数据
1)单目运算符 目:目标操作数
++ -- +(正号) -(负号)
前后缀运算:
-
前缀自加自减运算:先进行自加自减,再参与表达式运算
-
后缀自加自减运算:先参与表达式运算,在进行自加自减
#include <stdio.h>
int main(int argc, char const *argv[])
{
int a = 10;
int b = 20;
int c = ++a; // a先自加再赋值给c
int d = b++; // b先赋值给d再自加
printf("%d,%d,%d,%d\n",a,c,b,d);
int e = 2;
int x = (e++)+(e++);// 错误的写法,两个单目运算符不能进行双目运算
printf("x:%d,e:%d\n",x,e);
int b1 = 2;
int y = (b1++)+(++b1);//(错误的)
printf("b1:%d,e:%d\n",b1,y);// b1:4 y : 6
return 0;
}
error: multiple unsequenced modifications to [-Werror,-Wunsequenced]//多次非顺序修改
总结就是不要将自增或自减运算符与赋值运算符等其他运算符复合使用。
2)双目运算符
+ - * / %
printf("%d\n",3/2);// 一个整数除以另一个整数,小数被舍弃
printf("%f\n",3*1.0/2);// 如果想要小数,那么可以*1.0,隐式类型转换 1.500000printf("%d\n",10%3);//%取余运算符的左右两边必须都是整数
// 一般取余运算符在我们编程开发中用于控制数据的大小范围
srand(time(NULL));
// 获取随机数因子int a9 = rand()%5;
// rand()得到一个随机数0-4printf("%d\n",a9);
2. 关系运算符
注意关系运算符的值为布尔值 也就是说要么关系成立(1) 要么不成立(0)
1 > 10 20 < 30
int a = 10; int b = 20;
a != b;// 1
a == b; // 0
关注点:
-
关系运算符用于判断运算符两边的表达式是否满足给定的大小条件
-
由关系运算符组成的表达式称为关系表达式,其值为布尔型
-
判断是否相等是双等号==,而不是一个等号
3. 逻辑运算符
运算规则:
-
逻辑反:将逻辑真、假翻转,即真变假,假变真
-
逻辑与:将两个关系表达式串联起来,当且仅当左右两个表达式都为真时,结果为真。
-
逻辑或:将两个关系表达式并联起来,当且仅当左右两个表达式都为假时,结果为假。
特殊规则:
-
在逻辑与运算中,如果左边表达式的值为假,那么右边表达式将不被执行。
-
在逻辑或运算中,如果左边表达式的值为真,那么右边表达式将不被执行。
4. 位运算符(重点,对整个变量的某一位操作)
~ : 按位取反---单目运算符,数据将每一个bit位取反,1变0,0变1
&:按位与,两个都为1,结果才为1
-
1 & 1 == 1
-
1 & 0 == 0
-
0 & 0 == 0
-
0 & 1 == 0
| :按位或,两个都为1,结果才为1
-
1 | 1 == 1
-
1 | 0 == 1
-
0 | 1 == 1
-
0 | 0 == 0
^ : 按位异或 --- 不同为1,相同为0
-
1 ^ 0 == 1
-
0 ^ 1 == 1
-
0 ^ 0 == 0
-
1 ^ 1 == 0
<< : 左移,按bit位往左移动
1.无符号左移:规律(只要不越界,满足 number*2^n)
2.有符号左移
>> : 右移
1.无符号右移,规律(number / 2^n)
2.有符号右移
注意:
1.在进行移位运算的时候,凡是被移出去的位都丢弃,凡是空出来的都补零,移位运算是针对的是无符号整数。
2. 如果非要进行有符号的移位运算,那么左移的时候,空出来的补0,右移的时候,空出来不符号位(原码阶段);
-
位运算符操作的对象是数据中的每一位
-
运算规则:
-
位逻辑反、位逻辑与、位逻辑或拥有与逻辑运算相似的规则和一样的真值表。
-
异或运算:相同为0,不同为1
-
移位运算:移出去的不要,空出来的补零。移位运算都是针对无符号数的运算。
-
结论:
无符号整数左移,并且有效数据1不丢失时,假设 data << n,等于 data * 2^n
无符号整数右移,并且有效数据1不丢失时,假设 data >> n,等于 data / 2^n
5. 特殊运算符
赋值运算符
-
不能对常量赋值
-
只能对变量赋值
-
不能对数组赋值
-
可以连续赋值,从右往左
-
赋值运算符的左边(左操作数)必须是可写的地址空间
复合赋值符
-
当左右两边有相同的操作数时,采用复合赋值符不仅直观,且能提高运算效率
-
除了下述10个复合运算符之外,生造别的复合运算符是非法的
6. 条件运算符(三目运算符,重点)
-
唯一需要三个操作数的运算符
-
语法:表达式1?表达式2:表达式3
-
释义:当表达式1为真时,去表达式2,否则取表达式3
7. sizeof 运算符
-
含义:计算指定数据类型或者变量所占据内存的字节数
-
语法:sizeof(类型)、sizeof(变量),计算变量的字节数时圆括号可以省略
8. return运算符
-
含义:退出某个函数(如果退出的是主函数main,那么整个程序也就推出)
-
语法:必须出现在函数体内,可以带函数对应类型的数据
9.逗号表达式:
(表达式1,表达式2,表达式3,... 表达式n)
求值顺序:
先求表达式1,再求表达式2,再求表达式3,最后求表达式n
整个逗号表达式的值为n的值
注意:
1.逗号表达式的优先级最低
2.运算顺序是从左往右
3.整个逗号表达式的值取决于最右边的表达式的值
10. 优先级与结合性
-
当表达式出现不同的运算符时,根据优先级来决定谁先执行,比如先乘除后加减
-
当表达式中出现多个相同优先级的运算符时,更具结合性决定谁先运行,比如从左到右
二路分支
-
逻辑:程序中某段代码需要在满足某个条件时才能运行
-
形式:
-
if语句:表达一种 如果-则的条件执行关系
-
if-else语句:表达一种 如果-否则 的互斥分支关系
-
#include <stdio.h>
int main()
{
int number;
scanf("%d",&number);
printf("%d\n",number%2==0);
// if(number % 2 == 0) // 如结为真执行以下内容
// {
// printf("偶数\n");
// }
// else // 否则执行以下内容
// {
// printf("奇数\n");
// }
// 二路分支
// 如果if条件满足的情况下,只有一条语句,可以不用加{}
// 多余一条语句需要加{};
if(number % 2 == 0)
{
printf("我是");
printf("偶数\n");
}
else
printf("奇数\n");
// 多路分支,互斥关系,如果条件1和条件2成立,则只执行条件1
if(number > 0 && number <= 10)
{
printf("蛋炒饭\n");
}
else if(number >= 10 && number <= 20)
{
printf("黄焖鸡\n");
}
else if(number > 20 && number <= 30)
{
printf("KFC\n");
}
else
{
printf("饭堂随便吃\n");
}
// 嵌套分支
if(number > 400)
{
int score;
printf("面试成绩:");
scanf("%d",&score);
if(score > 80)
{
printf("欢迎来到合工大研究院\n");
}
else
{
printf("再接再厉\n");
}
}
return 0;
}
注意:
-
只要表达式的值为真(非0),则执行{}复合语句
-
if语句可以单独使用,else语句不可以,else语句必须根if语句配套使用
-
不管是if语句还是else语句,代码块都必须使用大括号{}括起来,否则只有首句有效
多路分支
根据不同的条件执行不同的代码片段
switch(n)//n只能是整数以及字符
{
case 1:
printf("one\n");
break;
case 2:
printf("two\n");
break;
case 3:
printf("three\n");
break;
default:
printf("其他数字\n");
}
要点解析
-
switch(n)语句中的n必须是一个整型表达式,即switch判断的数据必须是整型或者字符
-
case语句只能带整型常量,包括普通整型或字符,不包括const型数据
-
break语句的作用是跳出整一个switch结构,没有break程序会略过case往下执行
-
default语句不是必须的,一般放在最后面(因此不需要break)
const
-
逻辑:使一个变量不可修饰
-
作用:
-
修饰普通变量,使之不可修改
-
修饰指针变量,使之不可修改或者使其指向的目标不可修改
-
while与do...while循环
逻辑:使得程序中每一段代码可以重复循环的运行
形式:
-
while循环:先判断,再循环
while(表达式)// 表达式的值为真的时候进入循环体,为假退出
{
}
while(1)// 死循环 等价于 while(1);
{
}
如果循环体内只有一条语句,那么{}可以省略
while(1)
printf("11\n");
do-while循环:先循环,再判断
格式
do
{
循环体;
}while(表达式)
// 循环输出一系列整数,直到100为止
int a;
scanf("%d", &a);
do
{
printf("%d\n", a);
a++;
} while(a <= 100);
语法点:
-
while 循环先进行判断,条件为真后才执行循环体,因此循环体可能一遍也不执行。
-
do-while 循环先执行循环体,再进行判断,因此循环体至少会执行一遍。
-
do-while 循环中的 while 语句后面有分号;
for循环
逻辑:与 while 循环类似,但更加紧凑,for 循环将控制循环的变量集中在一行
for(初始表达式1;判断表达式2;循环操作表达式3)
{
循环体;
}
// 第一条表达式只执行一遍i = 0只执行一遍
// 然后执行表达式2,判断i 是否小于等于5,如果为真则执行{}里面的内容
// 最后执行表达式3,i++
// 然后一次循环完成再重新执行表达式2,判断i是否小于5,如果为真会执行
// {}里面的内容,最后执行表达式3,i++,依次类推,直到表达式2为假
// 则退出循环体
for(int i = 0; i <= 5; i++)
{
printf("i:%d\n",i);
}
// 死循环
for(;;)
{
}
或者
for(;;);
//多变量
for(int i = 0,j = 0; i < 5; i++,j++)
{
printf("i:%d j:%d\n",i,j);
}
语法点:
-
循环的标准语法是: for(表达式1 ; 表达式2 ; 表达式3)
-
表达式1一般用来初始化循环控制变量
-
表达式2一般用来作为循环判定条件,为真则进入循环,为假则跳出循环
-
表达式3一般用来更新循环控制变量
-
三个表达式均可以省略,但分号不能省略
-
while注重循环条件,for注重循环次数
break(退出)与continue(继续)
-
运用场景与特点
-
break关键字只能用于循环(while for do...while)和switch语句中,表示结束循环或者跳出switch语句
-
break关键字只能跳出最近一层的循环,也就是说,如果有多重循环,只能跳出最靠近break语句那层循环
-
break关键字 不能 单独用于 if语句中,除非if语句外面包含了循环
-
-
逻辑:
-
continue关键字只能用于循环体中(while do...while for),用于提前结束当前循环体后,又从最近一层循环体开始执行
-
continue关键字不能 单独用于 if语句或者switch 语句中,除非外面包含了循环
-
break:① 跳出 switch 语句; ② 跳出当层循环体while(1){while(1){break;}}
-
continue:结束当次循环,进入下次循环
-
goto语句
逻辑:无条件跳转
goto 语句标号;//程序会直接跳转到语句标号的地方执行
语句标号:
-
语法:
-
goto语句直接跳转到本代码块中的标签处
-
标签指的是以冒号结尾的标识符
-
-
作用:
-
goto语句的无条件跳转不利于程序的可读性,一般不建议使用
-
goto语句常被用在程序的错误处理中
-