《 C 语言的一些“骚操作”及其深层理解》之多用()无坏处
扫描二维码
随时随地手机看文章
多用()无坏处
!0+1,它的值等于多少?其实连我这样的老手也不能马上给出答案,2还是0?按C语言规定的运算符优先级来说,应该是!大于+,所以结果应该是2。
但是如果把它放在宏里,有时候就开始坑人了:
#define VALUE !0+1
int a;
a=VALUE&0;
踩过此类坑的人无需多说,自能领会。a=2&0呢,还是a=!0+1&0呢?它们的值截然不同。
这里出现了一些运算优先级和结合律的差错。为了让我们的语义和意图正确的得以表达,所以建议多用一些()。
#define VALUE ((!0)+1)
int a;
a=VALUE&0;
这样,a的值就一定是0了。
另外,有时候优先级还与C语言编译器有关,同一个表达式在不同的平台上,可能表达的意义是不同的。所以,为了代码的可植移性、正确性以及可读性,振南强烈建议多用一些()。
==的反向测试
C语言中的=与==,有时候是一个大坑。主要体现在条件判断时的值比较,如下例:
int a=0;
If(a=1)
{
//代码
}
也许我们的原意是判断a若为1,则执行。但实际上if根本不起作用,因为错把==写成了=。
C语言中的赋值操作也是一种表达式,称为赋值表达式,它的值即为赋值后变量的值。而C语言中条件判断又是一种宽泛的判断,即非0为真,为0则假。所以if(a=1)这样的代码编译是不会报错的。
这种错误通常是很难排查出来的,尤其是在复杂的算法中,只能一行行代码的跟踪。所以对于变量值的比较判断,振南建议使用“==的反向测试”,并养成习惯。
int a=0;
if(1==a)
{
//代码
}
如果把==错写成了=,因为常量无法被赋值,所以编译时会报错。
赋值操作的实质
原来一位哈工程理学院教授(搞数学的)讲述了自己的一个困惑,一直以来都被我们当成一个笑话在说。他学C语言的时候,首先a=1,然后后面又来一个a=2,这让他非常不解,a怎么可能同样等于1又等于2呢?
其实这是因为他对计算机运行机制不了解,这个a不是他数学稿纸上的代数变量,而是计算机中实实在在的“电”,或者说“信号”,如图2.7所示。
图2.7 计算机中CPU与存储器的寻址与数据传输
其实不限于C语言,所有编程语言的目的都是控制计算机硬件,实现电信号的传输、存储等操作,最终达成某一功能。变量是存储器中的一小块空间,它源自于形如int a这样的代码编译后由编译器所作的存储器分配。对变量的赋值就是CPU内核通过三总线将数据传输到存储器特定地址单元上的过程。所以,a=1;a=2;只是两次数据传输过程而已。
这个教授当时算是个外行,其实对于我们也是一样的,想要真正掌握编程语言,只流于代码表面的意思是不行的,必须对它在硬件上产生的操作有明确的认识,对计算机内部的运行机理有深入理解才可以。