一、什么是语句&表达式
- 语句:C语言中由一个分号隔开的就是一条语句
- 表达式:用操作符把变量连接起来的式子
二、bool类型与零值进行比较
- bool是C99引入的,之前没有,使用时需要头文件<stdbool.h>
- bool类型的使用:
#include <stdio.h> #include <stdbool.h> //没有这个头文件会报错,使用新特性一定要加上 int main() { bool ret = false; ret = true; printf("%d\n", sizeof(ret)); //vs2013 和 Linux中都是1 return 0; }
bool ret = false(true)
推荐写法
三、double类型与零值进行比较
- 浮点数在内存中储存的时候是有精度损失的(可能变大也可能变小)
- 浮点数在比较是否相等时绝对不能使用 == 来比较,因为浮点数本身有精度损失进而导致结果有细微差别
浮点数的比较方法
- fabs(x)求x的绝对值 需头文件<math.h>
- 应该进行范围精度比较:(x-y) > -精度 && (x-y) < 精度 精简版:fabs(x-y)<精度
- 精度可以自己设置,也可以使用系统精度(推荐)
- 系统精度:DBL_EPSILON FLT_EPSILON 头文件<float.h>
- fabs(x-y) < xxx_EPSILON说明x与y相等
- xxx_EPSILON是最小误差,是xxx_EPSILON+n不等于n的最小正整数
- fabs(a-0) 或fabs(a) < xxx_EPSILON说明a与0相等
-
为什么不是 <=呢?:如果fabs(a) <= xxx_EPSILON说明a本身已经能引起其他和它相+-的数据本身的变化了,不符合0的概念
四、指针与零值比较
- 0 '\0' NULL在数值上完全一样都为0
- 类型是不同的:int a = 0; char c = '\0'; int *p = NULL;
-
如何理解强制类型转换:不改变内存中的数据,只改变对应的类型(看待方式的改变)
-
真正的转换:改变内存中的数据
推荐写法
五、条件判断语句
1、if语句
- if (flag == 10){ ……
}①:先执行()中的表达式和函数,得到真假结果(true or false逻辑结果) ②:条件 判定功能 ③:进行 分支功能 - else 与 if的匹配:就近原则
2、Switch case语句
- 该组合一般只能进行整型匹配或整型表达式(int char)
- switch无判定和分支功能,本质是拿着后面的整型变量在case中依次匹配
- case完成判断,break完成分支
- 推荐:最后必须使用default,即使程序真的不需要default处理,也应保留以下语句:
- default:
- break;避免让人误以为忘了default处理
- case和break之间不能定义变量,若要定义,需要在case后面加{ }(在vs2022中此方法错误)或封装成函数
- default可以放在任何位置但习惯上放最后
推荐写法
- ①:按A-B-C或1-2-3的顺序排列
- ②:把正常情况放在前面,异常放后面
- ③:在正常情况下,最常执行的放前面,不常执行的放后面
总结switch && case && break && default
- switch语句结构中,case完成判定功能,break完成分支功能,default处理异常情况
- case:执行语句 = 1:多,多条语句不能定义变量如需定义①:用{ }括起来②:封装成函数,进行函数调用
- case:执行语句 = 多:1,多条case后不加break
- default可以放在任何地方,推荐放在最后
- case后的整型不能是:const int a = 10, case a:(a不是真正的常量,可以间接修改【后面在const关键字会讲到】)
六、循环语句
- do while循环,while后面的分号记得要加,至少执行一次
- break:跳出循环 continue:跳出本次循环(先更新条件,再返回条件判定处)
循环语句注意事项
- ①:尽可能将最长的循环放到内层,最短的循环放到最外层,以减少CPU跨循环层的次数,提高效率
- ②:for循环的内部采用前闭后开的写法:循环次数明确便于进行个数计算
七、易错代码分析
#include <stdio.h>
#include <string.h>
int main()
{
char a[1000];
for (int i = 0; i < 1000; i++)
{
a[i] = -1 - i;
}
printf("%zd\n", strlen(a));
return 0;
}
-1 - i = -1 + (-i)
-1的原码:1000 0001 反码:1111 1110 补码:1111 1111
i == 1 -1 + (-1)(补码相加):1111 1111 + 1111 1111 = 1 1111 1110 char有8个比特位,发生截断,存1111 1110,原码为:1000 0010,转十进制为-2
i == 127 (-i)的原码:1111 1111 反码:1000 0000 补码:1000 0001 1111 1111 + 1000 000 = 1 1000 0000发生截断,存1000 0000,转十进制为-128
i == 128 (-i)的原反补码:1000 0000 1000 0000 + 1111 1111 = 1 0111 1111发生截断,存0111 1111转化为十进制是127
规律:i:0 1 ————> 127 128 ————> 255
a[i] : -1 -2 ————> -128 127 ————> 0
一共有256个元素,但最后一位是'\0',不计入strlen中,故最终结果为255
'\0' = 0, 属于字符结束标识符,不属于字符串的内容,占一个字节,'\0'与'0'不同,'0'的ASCII码值是48,'\0'的ASCII码值是0
#include <stdio.h>
int main()
{
unsigned int i;
for (i = 9; i >= 0; i--)
{
printf("%u\n", i);
}
return 0;
}
for循环中,比较的过程一定需要将数据i读取出来,i是无符号整型,以无符号数的方式读取i,i永远大于0,此代码死循环
建议:所有无符号常量都有带有字母u后缀 unsigned int a = 10u;
个人主页:是冬至呀-CSDN博客