C语言深度剖析(贰)

​​​​​一、什么是语句&表达式

  1. 语句:C语言中由一个分号隔开的就是一条语句
  2. 表达式:用操作符把变量连接起来的式子

二、bool类型与零值进行比较

  1. bool是C99引入的,之前没有,使用时需要头文件<stdbool.h>
  2. 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)

推荐写法

  1. bool类型的使用方法

 三、double类型与零值进行比较

  1. 浮点数在内存中储存的时候是有精度损失的(可能变大也可能变小)
  2. 浮点数在比较是否相等时绝对不能使用 == 来比较,因为浮点数本身有精度损失进而导致结果有细微差别
  3. 精度损失

 浮点数的比较方法

  • 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的概念

 四、指针与零值比较

  1. 0 '\0' NULL在数值上完全一样都为0
  2. 类型是不同的:int a = 0; char c = '\0'; int *p = NULL;
  3. 如何理解强制类型转换:不改变内存中的数据,只改变对应的类型(看待方式的改变)

  4. 真正的转换:改变内存中的数据

推荐写法

五、条件判断语句

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关键字会讲到】)

六、循环语句

  1. do while循环,while后面的分号记得要加,至少执行一次
  2. 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博客

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值