C语言经典错误总结(一)

注:本文是结合《C陷阱和缺陷》所写!

一.=和==

我们都知道在C语言中**=** 表示赋值操作符,**==**表示比较,那么你知道为啥单等号为=,双等号为比较吗?

这里扩展下:因为在C语言中赋值操作符相对于比较符号较常出现,因此字符较少的符号=就被赋予了更常用的含义---赋值操作。

但是这样的便利却带来了一个非常常见错误,赋值操作符和比较运算错用!

看案例:

cs 复制代码
#include <stdio.h>
int main()
{
	char c;
    scanf("%c",&c);
	while (c = ' ' || c == '\t' || c == '\n')
	{
		printf("hello\n");
	}
	return 0;
}

你猜猜结果为啥呢?

结果为无限循环,原因就是因为将第一个==错写成了=,导致出现下述情况:

||优先级大于=优先级(逻辑运算符优先级大于赋值运算符优先级),所以该式子:c = ' ' || c == '\t' || c == '\n'是将 ' ' || c == '\t' || c == '\n'表达式结果赋值给c,然后判断是否为真,是真就继续下循环,因此出现无限循环的情况。

在为大家写一种两者区分写的特殊情况:

cs 复制代码
#include <stdio.h>
int main()
{
	int x;
	int y;
	if (x = y)
	{
		;
	}
	return 0;
}
//目的是将y的值赋值给x,并判断新值是否为0

如果我们完成上述目的直接这样写,可能你所在的编译器不会报错,但实际这种代码是非常不可取的,我们可以这样写:

cs 复制代码
#include <stdio.h>
int main()
{
	int x;
	int y;
	if ((x=y)!=0)
	{
		;
	}
	return 0;
}

这样可以目的一目了然,也可以防止自己误判!

总结:

因此在写C语言代码用到=和==时,一定要问自己一句,到底要干什么!!!

二.词法分析之"贪心法"

我们知道C语言符号分为单字符符号和多字符符号,那么你知道计算机是如何判断连续的字符是哪种符号吗?比如:a+++++b如何区分呢?

C语言定义了一个符号规则:

每个符号应该包含尽可能多的字符!

简单理解就是编译器分解符号的方法是:从左向右一个字符一个字符的读入,如果该字符能够组成一个已存在的符号或一个符号的部分,就继续读取下一个字符,重复该操作直到读入的字符组成的字符串不再可能组成一个有意义的符号停止,该策略就为"贪心法"。

在这里补充一个知识:除字符串和字符常量,符号的中间不能镶嵌空白(空格符,制表符和换行符)

看案例:

cs 复制代码
#include <stdio.h>
int main()
{
	int a = 3;
	int b = 3;
	int c = 0;
	c = a---b;
	printf("a---b=%d\n", c);
	a = 3; b = 3;
	c = a -- - b;
	printf("a -- - b=%d\n", c);
	a = 3; b = 3;
	c = a - -- b;
	printf("a - -- b=%d\n", c);
}

你能得出三个printf的结果吗?(联系上面的贪心法规则)

结果如下:

解释:

我们可以将上面的代码看成这样:

cs 复制代码
#include <stdio.h>
int main()
{
	int a = 3;
	int b = 3;
	int c = 0;
	//c = a---b;
    c=(a--)-b;
	printf("a---b=%d\n", c);
	a = 3; b = 3;
	//c = a -- - b;
    c=(a--)-b;//忽略空格
	printf("a -- - b=%d\n", c);
	a = 3; b = 3;
	//c = a - -- b;
    c=a-(--b);
	printf("a - -- b=%d\n", c);
}

从而得到结果!

关于符号的准二义性还有这些:

cs 复制代码
y=x/*p;
y=x/(*p);

本意是将x除以指针p指向的值,再把所得的商赋值给y,结果写成了第一行的代码,显然,问题大了,在编译器中看到/*就会被认为代码注释的开始,直到找到*/结束,所以我们因该写成第二行。

这里我们再回到开头这题:

cs 复制代码
a+++++b;
//可以理解为((a++)++)+b;

三.对标准输入输出printf和scanf理解

我们直接看案例:

cs 复制代码
#include <stdio.h>
int main()
{
	int i = 3;
	printf("%d,%d\n", i++, i++);
}

结果为:

为啥呢?不应该是 3,4吗?

在这里我们必须知道标准输入输出规则:printf从右向左输出,scanf从左向右输入

因此我们是先算后面一个i++,在算前一个i++,结果为:4,3

学会了吗?

再看一个代码:

cs 复制代码
#include <stdio.h>
int main()
{
	printf("%d", printf("%d", printf("43")));
	return 0;
}

结果为:

这是因为printf也有返回值,返回值是输出的字符数~!

最后,希望大家C语言学习犯错越来越少,加油!!!

相关推荐
Fairy_sevenseven2 分钟前
【二十八】【QT开发应用】模拟WPS Tab
开发语言·qt·wps
蜡笔小新星10 分钟前
Python Kivy库学习路线
开发语言·网络·经验分享·python·学习
凯子坚持 c10 分钟前
C语言复习概要(三)
c语言·开发语言
无限大.22 分钟前
c语言200例 067
java·c语言·开发语言
余炜yw23 分钟前
【Java序列化器】Java 中常用序列化器的探索与实践
java·开发语言
无限大.24 分钟前
c语言实例
c语言·数据结构·算法
篝火悟者25 分钟前
问题-python-运行报错-SyntaxError: Non-UTF-8 code starting with ‘\xd5‘ in file 汉字编码问题
开发语言·python
Death20027 分钟前
Qt 中的 QListWidget、QTreeWidget 和 QTableWidget:简化的数据展示控件
c语言·开发语言·c++·qt·c#
六点半88829 分钟前
【C++】速通涉及 “vector” 的经典OJ编程题
开发语言·c++·算法·青少年编程·推荐算法
惜.己29 分钟前
javaScript基础(8个案例+代码+效果图)
开发语言·前端·javascript·vscode·css3·html5