C语言的易错知识点汇总

C语言的易错知识点汇总

一、整型变量

1.1 补码的计算方法

1.1.1 关键概念回顾

  • 位数(n):补码表示依赖于固定的位数(如8位、16位、32位等)。最高位(最左边的位)是符号位:0表示正数,1表示负数。
  • 补码定义:对于一个负数 (x)(其中 (x < 0)),其补码是通过以下步骤计算的:
    1. 取 ( |x| )(绝对值)的二进制表示。
    2. 对所有位取反(0变1,1变0)。
    3. 将结果加1。

1.1.2 正数的补码是其本身

1.1.3 另一种方法:求一个正数对应的负数的补码

  1. 先写出正数的二进制数。
  2. 从二进制数的右边开始,遇到第一个1之前,全部填0.
  3. 遇到第一个1之后,把1填写来。
  4. 1之后的全部取反。
    如此就得出了负数的补码。
    举例:十进制数字-12的补码计算方法:
  5. 先写12的二进制数:0000 1100
  6. 从右往左,依次看有没有1,最后两位都是0,就把这两个0抄下来。
  7. 看到第3位是1,就把这个1抄下来。
  8. 从第4位开始,全部取反。就是说,第4位的1,取反,得到0。其余各位也取反。
    于是,得到-12的补码是1111 0100。

1.2 从负数的补码反推这个负数的值

如果补码的最高位是1(表示负数),则按以下步骤操作。如果最高位是0,则表示正数,值就是二进制本身。下面讲从负数的补码入手,反推这个负数的值。

  1. 方法一、从负数的补码计算方法反推
    将负数的补码,比如说0xFFFF FFFE,减一,得到0xFFFF FFFD,之后按位取反,我们只关心最后的4位:1101,按位取反就是0010,前面都是0,那么这个值是2,前面加负号就是-2。换言之,补码为0xFFFF FFFE的有符号数对应的数值是-2
  2. 方法二、利用公式计算
    例如负数的补码是0xFFFF FFFE,将其当作无符号数计算一下它的值,它是十进制的65534,减去2的16次方,即65536(因为0xFFFF FFFE16位的数值),得到的值是65534 - 65536 = -2,即补码为0xFFFF FFFE的有符号数对应的数值是-2

二、while循环容易忽视的细节

2.1 while循环和循环条件的执行顺序

先看代码,之后想一个问题。

void memset(void *s, uint8_t c, size_t n)
{
   
   
    uint8_t *p = (uint8_t *)s;
     printf("memset函数刚进来的时候,n = %d\r\n", n);
    while (n--)
    {
   
   
        printf("在while循环中, n = %d\r\n", n);
        *p++ = (uint8_t)c;
    }       
    printf("\r\n离开memset函数的时候,n = %d\r\n\r\n", n);     
}

调用该函数:

	char TaskInfo[10];
	memset(TaskInfo,0,10);	

2.1.1 问题

请问,while是先执行完n--,再判断结果是否不等于0,如果不等于0,就执行循环?还是先判断n是否不等于0,(判断完成之后,不管结果怎么样,执行n--),如果n--之前不等于0,就循环?
不妨大家复制我的代码,测试一下。公布一下答案:是后者
先判断n != 0是否成立,如果成立,就执行循环。但在循环之前,一定要先执行n--

2.1.2 串口打印结果

在这里插入图片描述

将代码修改一下,更明显。

void memset(void *s, uint8_t c, size_t n)
{
   
   
    uint8_t *p = (uint8_t *)s;
    n = 1;
    printf("memset函数刚进来的时候,n = %d\r\n", n);     
    while (n--)
    {
   
   
        printf("在while循环中, n = %d\r\n", n);
        *p++ = (uint8_t)c;
    }        
    printf("\r\n离开memset函数的时候,n = %d\r\n\r\n", n);    
}

实验结果:
在这里插入图片描述

2.2 上一个问题的延申

当然即便n != 0不成立,也要执行n--。也就是说,即便n = 0,不满足循环条件,也要继续执行n --。这么说,有依据吗?试试看!
修改代码如下:

void memset(void *s, uint8_t c, size_t n)
{
   
   
    uint8_t *p = (uint8_t *)s;
    n = 0;
    printf("\r\nmemset函数刚进来的时候,n = %d\r\n", n);     
    while (n--)
    {
   
   
        printf("\r\n在while循环中, n = %d\r\n", n);
        *p++ = (uint8_t)c;
    }        
	printf("\r\n离开memset函数的时候,n = %d\r\n\r\n", n);    
}

2.2.1 串口打印结果

在这里插入图片描述

2.3 问题再次延申:将n--改为--n会怎么样?

先看代码:

void memset(void *s, uint8_t c, size_t n)
{
   
   
    uint8_t *p = (uint8_t *)s;
    printf("\r\nmemset函数刚进来的时候,n = %d\r\n", n);     
    while (--</
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值