C语言的易错知识点汇总
一、整型变量
1.1 补码的计算方法
1.1.1 关键概念回顾
- 位数(n):补码表示依赖于固定的位数(如8位、16位、32位等)。最高位(最左边的位)是符号位:0表示正数,1表示负数。
- 补码定义:对于一个负数 (x)(其中 (x < 0)),其补码是通过以下步骤计算的:
- 取 ( |x| )(绝对值)的二进制表示。
- 对所有位取反(0变1,1变0)。
- 将结果加1。
1.1.2 正数的补码是其本身
1.1.3 另一种方法:求一个正数对应的负数的补码
- 先写出正数的二进制数。
- 从二进制数的右边开始,遇到第一个1之前,全部填0.
- 遇到第一个1之后,把1填写来。
- 1之后的全部取反。
如此就得出了负数的补码。
举例:十进制数字-12的补码计算方法: - 先写12的二进制数:0000 1100
- 从右往左,依次看有没有1,最后两位都是0,就把这两个0抄下来。
- 看到第3位是1,就把这个1抄下来。
- 从第4位开始,全部取反。就是说,第4位的1,取反,得到0。其余各位也取反。
于是,得到-12的补码是1111 0100。
1.2 从负数的补码反推这个负数的值
如果补码的最高位是1(表示负数),则按以下步骤操作。如果最高位是0,则表示正数,值就是二进制本身。下面讲从负数的补码入手,反推这个负数的值。
- 方法一、从负数的补码计算方法反推
将负数的补码,比如说0xFFFF FFFE,减一,得到0xFFFF FFFD,之后按位取反,我们只关心最后的4位:1101,按位取反就是0010,前面都是0,那么这个值是2,前面加负号就是-2。换言之,补码为0xFFFF FFFE的有符号数对应的数值是-2。 - 方法二、利用公式计算
例如负数的补码是0xFFFF FFFE,将其当作无符号数计算一下它的值,它是十进制的65534,减去2的16次方,即65536(因为0xFFFF FFFE是16位的数值),得到的值是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 (--</

最低0.47元/天 解锁文章
2338

被折叠的 条评论
为什么被折叠?



