运算符优先问题
举例:想实现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