C语言语法陷阱

运算符优先问题

举例:想实现r高四位与hi一致,第四位与low一致。像写出表达式如下

r=hi<<4+low
但是这句代码不能实现需要的功能,因为优先级的原因。它将被理解为:
r=hi<<(4+low)

为了实现原有功能,最简单的方法是加括号:r=(hi<<4)+low,原因在下面解释。

在C语言中,优先级有十五个之多。
图片来源图片来源
总结来说优先级关系:后缀运算符,单目运算符,算术运算符,移位运算符,关系运算符,逻辑运算符,条件运算符,赋值运算符
所以对以下的代码

x = income>200 && resi<5 ? 3.5 :2.0

其中优先级最低的是赋值运算符=
优先级最高的是关系运算符>,<,优先执行income>200和resi<5的判断
然后是逻辑运算符&&,将左右两关系运算结果与操作。
最后是三目运算符?:,判断左边与运算后结果进行三目运算选择
最终将计算结果赋值给x.

当运算符优先级相同时,按照结合性进行
举例:

a=b=10;

按照赋值运算的结合性事从右到左,即先进行b赋值为10,然后将b的值赋给a。相当于

b=10;
a=b;

语句结束标志的分号

当不小心多写了一个分号可能不会造成什么不良影响,会被视为空语句,可能编译器会给出一个警告

int a=4;;

特别需要注意的是在if和while中,比如一下这个例子

if(a==10);
	printf("a is equal to 10\n");

在if后跟了一个分号会导致程序被理解为

if(a==10)
	;
printf("a is equal to 10\n");

少写一个分号也会招致奇怪的错误。比如下面一个例子

if(n<3)
	return
m=10;
b=9;

return后面掉了一个分号,这段程序任然可以通过编译,只是会被理解为

if(n<3)
	return m=10;
b=9;

当程序函数申明返回值事void时,编译器会因为与返回类型不同而报错;当函数声明中省略掉返回值类型时,编译器会隐式的将返回类型视为int类型。上面错误就不会被检测到。当n>=3时,运行就会跳过m=10的赋值语句,导致极难发现的错误。

switch语句

考虑如下代码

switch(a):
	case 1:
		printf("yellow");
	case 2:
		printf("blue");
	case 3:
		printf("green");

当a=2时,输出结果是bluegreen,这既是C中的缺点,又是其优点。当有意省去一个break时,可以实现程序的控制。
比如一下程序完成了跳过空白字符,除了\n会将行数加一

case '\n':
	line++;
case '\t':
case ' ':

...

悬挂else问题

考虑如下代码

if(a<10)
	if(y==0) error();
else{
	z=a+y;
	printf("end");
}

但是实际运行结果是

if(a<10){
	if(y==0) 
		error();
	else{
		z=a+y;
		printf("end");
	}
}

因为else始终与同一对括号内最近的if匹配。C不像python,通过缩进控制程序结构。

注:文章参考于《C陷阱与缺陷》Andrew Koenig

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

帅逼码农

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值