正确理解C语言中几个特殊的运算符

Author: 邓益民 Date: 1996-12-13

        1.++与--运算符
        这是两个比较特殊的算术运算符。其特殊性在于:
        ①操作数必须是变量,如:++a,b--等;
        ②运算符具有双重作用,即不仅所构成的表达式有一个运算值,同时还会使操作数这一变量增1或减1。比如若已知int a=3,则表达式a++将导致:
        ·该表达式值为3;
        ·变量a增1,变成a=4。
        其中尤其需要注意的是上述第二个特殊性中表达式本身的运算值。初学者易犯的错误是认为a++就相当于a=a+1,即给变量a增1,而忽略了a++本身是一个表达式,而任何一个表达式都应有它的运算值,正如2+3这一表达式有值5一样。试看下面的一个例子(运行于Turbo C2.0,下同):
        main()
        {
        int n=1,s=0;
        while(n<=100)s+=n++;
        printf("\ns=%d",s);
        }
        这个程序用来求1+2+3+…+100的值。循环语句while的子语句s+=n++;中包含了+=和++这两个运算符。当循环进入第一次时n=1,此时n++(因++优先级高,故先计算)使得n增1变为n=2,但同时n++表达式值仍为1(因为是n++而非++n),故此时s+=n++是使s+=1,即s=1。如果不能正确理解++的这一双重作用,很容量理解s+=n++为:n=2及s+=n,从而得到s=2这一错误结果。
        2.赋值与复合赋值运算符
        类似于++、--运算符,=、+=、-=、*=、…这些运算符也具有双重作用,且要求其左操作数一定是变量。比如若已知int a=3,则a+=2这一表达式将导致:
        ·该表达式值为5;
        ·变量a变为a=5.
        此时需要注意的同样是不可忽略a+=2这一表达式值为5这个事实。
        又比如已知int a,b,c,程序要求给a、b赋值,而C则由a/b获得,此时可用如下语句:
        int a,b,c;
        c=(a=20)/(b=3);
        这样就由一个表达式语句获得了同时给三个变量赋值的效果。
        3.条件运算符
        条件运算符的特殊性似乎是由于它是唯一一个三操作数运算符。然而真正的特殊之处是它的三个操作数的运算顺序。由格式:
        <表达式1>?<表达式2>:<表达式3>
        不论表达式1、2、3中包含什么样优先级的其他运算符,条件表达式的运算顺序都是:先计算<表达式1>,若非0(即为逻辑真),则接着计算<表达式2>,并以此作为整个条件表达式的值,而不再计算<表达式3>;反之,若<表达式1>为0(即为逻辑假),则计算<表达式3>而不计算<表达式2>。
        比如若已知int a=1,考察表达式a?a--:a-1。如果按运算符优先级顺序,应行计算a--,使得a=0,且a--值为1,再计算a-1值为-1,最后由0?1:-1而得到结果-1。然而实际的运算顺序是:由a=1非0,计算表达式a--,从而知整个条件表达式值为1,且a=0,a-1根本未进行运算。
        当然,条件运算符所构成的条件表达式中其他运算符优先级仍然具有一定作用,如对于表达式:-3?-1:1,2,由于条件运算符?:的优先级高于逗号运算符,因此表达式-3?-1:1,2相当于(-3?-1:1),2而非-3?-1(1,2),因而其值为2而非-1。事实上,一个包括条件表达式的表达式中其他运算符的优先级决定了上述<表达式1>、<表达式2>、<表达式3>的范围。
        再比如下面一个程序用来将用户输入的小写字符改为大写字符输出:
        #include "stdio.h"
        main()
        {
        char ch;
        ch=getchar();
        'a'<=ch&&ch<="Z"?ch-=32:ch;
        putchar(ch);
        }
        程序通过判断ch是否为小写字符(介于a与z之间),再决定是计算表达式ch-=32(变成大写字符)或者保持ch不变。可见,正确理解条件表达式有助于我们写出更加简练的程序。
        (邓益民)