c语言语法学不好?学习的过程中经常犯错?一篇文章带你全方面看清C语言

在这里插入图片描述

1.词法常犯错误

1.1=和==的区别

很多刚学C语言的朋友,最容易犯的一个错误就是=和==混淆,本意是作比较运算符,却无意中误写成了赋值运算
例如:
本意是判断x是否等于y

if(x=y)
	break;

结果却是将y的值赋值给了x,然后检查该值是否等于零

1.2看似相同却另有乾坤

除了字符串和字符常量,符号的中间不能嵌有空白(空白符、制表符和换行符)

==//单个字符
= =//两个字符

例如:
也许你想表达的是用x除以p所指向的值,把所得的尚再赋值给y,实际却是/被编译器理解为一段注释的开始,直到遇到/出现才停止

y=x/*p

应该将其改写为

y=x/(*p) //p指向除数

这样才能达到你想要的效果

1.3字符和字符串

单引号括起的一个字符代表一个整数,而双引号括起来的一个字符代表一个指针

2.语法常犯错误

2.1运算符的优先级问题

C语言运算符优先级问题(由上至下,优先级依次递减)

运算符 结合性
() [] -> . 自左向右
! ~ ++ – - (type) * & sizeof 自右向左
* / % 自左向右
+ - 自左向右
<< >> 自左向右
< <= > >= 自左向右
== != 自左向右
& 自左向右
^ 自左向右
| 自左向右
&& 自左向右
|| 自左向右
?: 自右向左
assignments 自右向左
, 自左向右

因为函数调用优先级高于单目运算符的优先级,如果p是一个函数指针,要调用p所指向的函数,应该写成

(*p)()

如果写成

*p()

编译器会解释成

*(p())

++运算符的优先级是自右向左,因此

*p++

会被编译器解释为

*(p++)

即取指针p所指向的对象,然后将p递增1
而不是

(*p)++

即取指针p所指向的对象,然后将该对象递增1
重点:
1.任何一个逻辑运算符的优先级低于任何一个关系运算符
2.移位运算符的优先级比算术运算符要低,但是比关系运算符要高

2.2语句结束标志的分号

如果不小心多加了一个分号,可能会产生意想不到的后果。
如:

  1. 这个分号也许会被视作一个不会产生任何实际效果的空语句
  2. 编译器可能会报警告
  3. 如果在if或者while语句之后需要紧跟一条语句时,如果此时多了一个分号,原来紧跟在if或者while子句之后的语句就是一条单独的语句,与条件判断部分没有任何关系了

2.3“悬挂”else引发的问题

if(x==0)
	if(y==0) error();
else
	z=x+y;
	f(&z);

这段代码本意是应该有两种情况:
x等于0以及x不等于0.对于x等于0的情形,除非y也等于0(此时调用函数(error),否则程序不作任何处理;
对于x不等于0的情形,程序首先将x与y之和赋值给z,然后以z的地址为参数来调用函数f
然而这段代码实际上所做的却与我们想要的结果相差很大,原因在于C语言中有这样的规则,即else始终与同一对括号内最近的未匹配的if结合
正确的写法应该是

if(x==0){
    
    
	if(y==0)
		error();
}
else
{
    
    
	z=x+y;
	f(&z);

3.语义常犯错误

3.1边界计算和不对称边界

在C语言中,一个拥有n个元素的数组,却不存在下标为n的元素,其元素的下标范围是从0到n-1

3.2求值顺序

C语言中其他所有运算符对其操作数求值的顺序是未定义的,特别是赋值运算符并不能保证任何求值顺序
下面这种从数组x中复制前n个元素到数组y中的做法是不正确的,因为它对求值顺序做了太多的假设

i=0;
while(i<n)
	y[i]=x[i++];

上面的代码假设y[i]的地址将在i的自增操作执行之前被求值,这一点并没有任何保证!在C语言的某些实现上,有可能在i自增之前被求值,而在另外一些实现上,有可能与此相反。同理,下面这种版本的写法与前类似

f(x,y)

x和y的求值顺序是未定义的

g((x,y))

确定先x后y的顺序

3.3运算符&&、||和!

C语言中的两类逻辑运算符,某些时候可以互换,按位运算符&、|、和~,以及逻辑运算符&&、||、!。有时候你发现程序依旧可以照常运行,其实这都是巧合而已。
按位运算符&、|和~对操作数的处理方式是将其视作一个二进制的位序列,分别对其每个位进行操作
逻辑运算符&&、||、!对操作数的处理方式是:要么将其视作“真”,要么将其视作“假”。
因此,我们能够很容易求得这个表达式的结果:!10的结果是0,因为10是非0数,10&&12的结果是1,因为10和12都不是0;10||12的结果也是1,并且12根本不会被求值

3.4整数溢出

当两个操作数都是有符号操作数时可能发生溢出,而溢出的结果是未定义的

猜你喜欢

转载自blog.csdn.net/weixin_51799303/article/details/131235241