知识点1【运算符】
用算术运算符将运算对象连接起来的、符合C语法规则的式子,称为C算术表达式。
运算对象包括常量、变量、函数返回值等
1、算数运算符
+ - * / % += -= *= /= %=
1.1 /的运算对象全是整型(short int long),取整
5/2 == 2 3/4 == 0
1.2 /的运算对象有一个是实型(short int long),除法
5/2.0 == 2.5
total == 100
cur == 48
模拟进度条:
#include <unistd.h>
void test04()
{
int total = 10;
int cur = 0;
for (cur = 0; cur <= total; cur++)
{
printf("\r%d%%", (int)(cur / (float)total * 100));
fflush(stdout);//强制刷新缓冲区
sleep(1);
}
}
模拟时钟:
#include <unistd.h>
void test04()
{
int time = 0;
while(1)
{
printf("\r%02d:%02d", time/60,time%60);
fflush(stdout);//强制刷新缓冲区
sleep(1);
time++;
}
}
1.3 % 取余运算符
5%3 == 2 6%3 == 0
如果n%m==0 说明n被m整除
n%3范围:0~2
n%4范围:0~3
假如n>=0,那么n%m的范围:0~m-1
%的运算对象不能有实型。
1.4 += -+ *= 复合运算符
a+=5;//a=a+5
一定要将=右边看成一个整体
a*=5+2; ----> a = a * (5+2)
2、关系运算符
>、<、==、>=、<=、!=
3、逻辑运算符
1、逻辑与 &&
A && B A和B同时为真 整个表达式为真,只要有一个为假 整个表达式为假。
逻辑与的短路特性:如果A为假 系统将不会执行B(判断B的真假)。
2、逻辑或 ||
A || B A和B只要有一个为真 整个表示为真 同时为假 整个表达式才为假。
逻辑或的短路特性:A为真 不会继续判断B的真假。
3、逻辑非
!真 == 假 !假 == 真 在c语言中 0为假 其他都为真。
!-10 == 0 !0 == 1
能被4整除 但不能被100整除,或者能被400整除
((year%4==0) && (year %100 != 0)) || (year %400 ==0)
4、位运算符
位运算符操作二进制位的运算符。
1、& 按位与
语法:全1为1 有0为0
1010 0011
& 1111 0000
------------------
1010 0000
特点:和1与保持不变 和0与清0
场景:将指定位清0
案例1:假如data位8位寄存器,将第3、5 清0
data = data & 0b1101 0111;
data = data & 0xd7;//ok
2、| 按位或
语法:有1为1 全0为0
1010 0011
| 1111 0000
------------------
1111 0011
特点:和0或保持不变 和1或置1
场景:将指定为置1。
案例1:假如data位8位寄存器,将第4、6置1
data = data | 0b0101 0000;
data = data | 0x50;
data |=0x50;
3、~按位取反
按位取反一般配合&和|一起使用
语法:0变1 1变0
~(1010 1100) == 0101 0011
4、^ 按位异或
语法:相同为0 不能为1
1010 0011
^ 1111 0000
------------------
0101 0011
特点:和1异或取反,和0异或保持不变
场景:将指定为发生翻转。
//假如data为GPIO引脚寄存器 需要将P0输出PWM
while(1)
{
//data = data ^0b00000001;
data = data ^ 0x01;
sleep(1);
}
5、左移运算符:<<
左边丢弃 右边补0。
注意:左移的位数不要操作 变量自身的位数。
6、右移运算符:>>
如果data是无符号数,有符号正数 :右边丢弃 左边补0。
如果data是有符号数且为负数:
右边丢弃、左边补0。逻辑右移
右边丢弃、左边补1。算术右移
逻辑右移或算术右移 不是用户决定 是编译器决定的。
案例:写一个代码测试我们的编译器是逻辑右移还是算术右移。
7、左移和右移的补充
左移的补充
假如data为1字节 data==1==0000 0001 data=data<<0 data==0000 0001==1 data=data*2^0
假如data为1字节 data==1==0000 0001 data=data<<1 data==0000 0010==2 data=data*2^1
假如data为1字节 data==1==0000 0001 data=data<<2 data==0000 0100==4 data=data*2^2
......
假如data为1字节 data==1==0000 0001 data=data<<7 data==1000 0000==128 data=data*2^7
右移的补充(补0)
假如data为1字节 data==128==1000 0000 data=data>>0 data==1000 0000==128 data=data/2^0
假如data为1字节 data==128==1000 0000 data=data>>1 data==0100 0000==64 data=data/2^1
假如data为1字节 data==128==1000 0000 data=data>>2 data==0010 0000==32 data=data/2^2
......
假如data为1字节 data==128==1000 0000 data=data>>7 data==0000 0001==1 data=data/2^7
8、位运算的综合案例
案例1:假如data位8位寄存器,将第3、5 清0
data = data & 1101 0111
1101 0111== ~(0010 1000)
== ~(0010 0000 | 0000 1000)
== ~(0000 0001<<5 | 0000 0001<<3)
== ~(0x01<<5 | 0x01<<3);
data = data & ~(0x01<<3 | 0x01<<5);
data &= ~(0x01<<3 | 0x01<<5);//推荐
案例1:假如data位8位寄存器,将第4、6置1
data = data | 0101 0000
0101 0000 == 0100 0000 | 0001 0000
== 0000 0001<<6 | 0000 0001<<4
== 0x01<<6 | 0x01<<4
data = data | (0x01<<4 | 0x01<<6);
data |= (0x01<<4 | 0x01<<6);//推荐
5、三目运算符 ?:
表达式1 ? 值1:值2;
如果表达式1 为真 整个表达式的结果为值1否则为值2.
6、逗号运算符
void test08()
{
int data = 0;
//逗号优先级低于赋值运算符 所以先赋值
data = 1,2,3,4,5,6;//1
printf("data = %d\n",data);
//将()的结果赋值给data
//()是逗号运算符 从左往右 遍历 最后一个数就是()的结果
data = (1,2,3,4,5,6);//6
printf("data = %d\n",data);
}
7、运算符的优先级
优先级数值越小优先级越高,相同优先级看结合性
8、自增自减运算符
i++ i-- ++i --i
i++ 等价于 i=i+1;
i-- 等价于 i=i-1;
i++ ++i独立作为一条语句 没有区别
void test09()
{
int i = 3;
//i++;
++i;
printf("i=%d\n", i);//4
}
void test09()
{
// ++在i的右边 有个副作用 先使用 后加
int i = 3;
int j = 0;
j = i++; // j=i; i=i+1
printf("i=%d j=%d\n", i, j); //4 3
}
void test09()
{
// ++在i的左边 先加 后使用
int i = 3;
int j = 0;
j = ++i; // i=i+1;j=i;
printf("i=%d j=%d\n", i, j); // 4 4
}
知识点15【控制语句】
1、if语句 选择语句
1.1 独立if语句 只在乎项目某个结果
if(条件1)
{
语句1;
}
如果条件为真 执行语句1 否则跳出if
1.2 if....else 项目有两个结果 不会同时出现
if(条件1)
{
语句1;
}
else
{
语句2;
}
条件1为真 执行语句1 否则执行语句2;
1.3 if...else if ...else if ....else 项目有多个结果 但是同一时刻 只会出现一个
if(条件1)
{
语句1;
}
else if(条件2)
{
语句2;
}
else if(条件3)
{
语句3;
}
else//可省略
{
语句4;
}
如果条件1为真执行语句1 后续else if的条件将不会判断
如果条件1为假 才会判断下一个else if的条件是否成立
1.4 项目有多个结果 不知道是否同时出现 独立使用多条if
if(条件1)
{
语句1;
}
if(条件2)
{
语句2;
}
if(条件3)
{
语句3;
}
案例1:键盘输入一个数 判断它对3余数
void test10()
{
int data = 0;
printf("请输入一个int数值:");
scanf("%d", &data);
if(data%3 == 0)
{
printf("%d对3的余数为0\n",data);
}
else if(data%3 == 1)
{
printf("%d对3的余数为1\n",data);
}
else if(data%3 == 2)
{
printf("%d对3的余数为2\n",data);
}
}
2、switch语句
//计算表达式1的结果 与下方case后的值比较 如果相等 就从该case进入 遇到break跳出
//一般 每个case 下方都要有一个break
switch(表达式1)//表达式1中必须是char short int long 不能是float double
{
case 值1://case后面的值必须是常量或常量表达式
语句1;
break;//break在特殊情况下可以省略
case 值2:
语句2;
break;
case 值3:
语句3;
break;
default://可以省略
语句4;
break;
}
案例1:
3、for循环语句
for(初始语句 ;循环条件 ;步进语句 )
{
循环体;
}
初始语句:只会在判断循环条件前执行一次
循环条件:每次都要判断 如果循环条件为真 就进入循环体执行一次
步进语句:每次循环体执行结束后 自动执行步进语句,再去判断循环条件
案例1:以下代码循环的次数
void test13()
{
int i;
int sum;
//i是局部变量 不初始化内容不确定 导致i<=100的循环条件也不确定 所以不确定循环次数
for ( ; i <=100; i++)
{
sum = sum +i;
}
printf("sum = %d\n",sum);
}
break用于for跳出
continue结束本次循环立即进入下一次循环
for的死循环
for(;;)
{
}
for循环嵌套循环
分析内层循环时 注意:变化的数作为内层循环 不变的数作为外层循环
void test14()
{
int i = 7;
for (i = 1; i <= 9; i++)
{
int j = 0;
for (j = 1; j <= i; j++)
{
printf("%2d*%-2d=%-2d ", j, i, i * j);
}
printf("\n");
}
}
4、while循环
//用户实现初始化语句(重要)
while(循环条件1)
{
循环体;
//用户实现步进语句(重要)
}
for和while的选择:
如果有固定的循环次数 建议选择for
没有循环次数 但是有退出条件 建议选择 while
do
{
循环体;
}while(循环条件);
先执行一次循环体 再判断循环条件是否为真。
5、goto 跳转语句(少用)