C语言基础

    返回首页    发表留言
本文作者:李德强
          第三节 运算符和表达式
 
 

一、算数运算符和算数表达式

        基本的算数运算符包括加减乘除四则运算符和求余运算符:

+:加法运算符,双目运算符,双目运算符表示在符号的两侧有两个变量参与此运算。例如:a+b,a+3,4+6等。加法运算符具有右结合性。

-:减法运算符,双目运算符。同时它可以作为“负号”做为变量的负值运算的左结合性运算符。作为负运算符时为单目运算符,并具有左结合性。

*:乘法运算符,双目运算符,具有左结合性。

/:除法运算符,双目运算符,具有左结合性。在表达式中,如果参与运算的量都是整数,则结果为整数,并向0取整。如果参与运算的量有浮点数,则结果为双精度浮点数。

%:取余运算符:双目运算符,具有左结合性。要求参与运算的量必须为整数。

        在四则运算中可以使用多个运算符来实现一些比较复杂的表达式,例如:2 + 4 - 8 % 3或a + b - c * e等等,算数表达式的程序计算过程与我们平时使用的“先乘除后加减”的原则,也就是说在C语言中运算符的优先级是不同的,我们会在后续学习每一种运算符的优先级,而具有相同优先级的多个运算符时按其结合性进行计算。       

 

二、关系运算符和关系表达式

        关系运算符所构成的关系表达式的运算结果为0和1,用于表示“真”或“假”,这些关系表达式也被称为条件表达式,其实就是用于程序中的结果判断。例如我们在之前学习过while循环语句来使程序执行多次循环,但我们并不希望程序一直循环下去,而是希望程序在执行一段时间后,能够结束循环,靠的就是关系表达式的结果为真或假来确定程序继续循环还是结束循环。关系运算符有:

<:双目运算符,当左侧数值小于右侧时运算结果为真,否则为假。

>:双目运算符,当左侧数值大于右侧时运算结果为真,否则为假。

<=:双目运算符,当左侧数值小于或等于右侧时运算结果为真,否则为假。

>=:双目运算符,当左侧数值大于或等于右侧时运算结果为真,否则为假。

==:双目运算符,当左右两侧数值相等时运算结果为真,否则为假。

!=:双目运算符,当左右两侧数值不相等时运算结果为真,否则为假。

        例如:a < 3,b >= c,d == e,f != 3等均为关系表达式,它们的运算结果为真或为假, 为真是结果等于1,为假是结果等于0。而C语言中规定判断条件的结果为0时表示假,而非0表示真,所以说,除了1之外所有非0的数都可以做为关系表达式中结果的“真”。我们来举几个例子: 

 

int a = 3, b = 4, c = 4;
float e = 3.14, f = 3.14159;
printf("%d %d %d %d\n", 1 < 2, 1 >= 2, 3 == 4, 3 != 4);
printf("%d %d %d\n", a < b, a >= c, b >= c);
printf("%d %d\n", e == f, e < f);

1 0 0 1
1 0 1
0 1

        在条件表达式中还有一个比较特殊的表达式,就是问号表达式,它的使用方式如下:

条件表达式 ? 值A  : 值B

        问号表达式的作用是根据问号前面的条件表达式的结果来产生不同的值。如果条件表达式中的结果为真,则整个问号表达式的值为冒号左侧的值;如果条件表达式中的结果为假,则整个问号表达式的值是冒号右侧的值。例如:

 

printf("%d\n", 3 < 5 ? 8 : 9);
printf("%c\n", 3 > 5 ? 'T' : 'F');

8
F

 

 

三、位运算符和位运算表达式

        我们在前面章节中讲述了关于普通变量占用字节数的相关知识。例如:char型变量占用1个字节的内存空间,而short型变量占用2个字节的内存空间等。内存中8个bit位表示1个字节,也就是说对于char类型变量来说,它占用8个bit位,而short类型变量占用16个bit位。而每一个bit位在内存中都是采用2进制来表示的,也就是每一个bit位上的值只有0或1。例如一个char类型的变量如果它的值是75那么它在内存中字节的bit位的值如下:

 

0100 1011

 

        其中最左侧的bit位是其符号位,0表示正数,1表示负数,剩余的7个bit位最多可以表示128个整数,当符号位为0时它表示一个正数,值的范围为0 ~ 127,而当符号位为1时它表示一个负数,值的范围为-128 ~ -1。而计算机是采用补码的形式存放数值的,正数的补码是其本身,负数的补码为其反码加1,而一个数的反码即是其原码在每一个bit位上取反(0变1,1变0)详见《补码原理》

        所谓的位运算符和位运算表达式就是指针对某一个变量或数值对其所在内存中的bit位进行运算,操作符有:

&:与运算符,双目操作符,左结合性,表示将此运算符左右两端参与计算的量做与运算,表示将两个变量中每一个bit位做与,也就是bit位上的乘法运算 0 & 0 == 0、0 & 1 == 0、1 & 1 == 1。

|:或运算符,双目操作符,左结合性,表示将此运算符左右两端参与计算的量做或运算,表示将两个变量中每一个bit位做或,也就是bit位上的加法运算(不进位), 0 | 0 == 0、0 | 1 == 1、1 & 1 == 1。

~:反(为了跟!操作符表示的“非”做区分,这里称为“反”)运算符,单目操作符,表示将此运算符后的量中每一个bit位取反,即0变1,1变0。

^:与或运算符,双目操作符,左结合性,表示将此运算符左右两端参与计算的量做与或运算,与或运算的原则为:两个量中同一位bit上相同时结果为1,不同是结果为0: 0 | 0 == 1、0 | 1 == 0、1 & 1 == 1。

<<:左位移运算符,双目操作符,左结合性,表示将运算符左侧的量每一个bit的值向左侧移动,右侧bit位补0,移动的位数为其右侧的量。例如3 << 2表示将3中的每一个bit位0000 0011都向左移动2位,结果为0000 1100即12。

>>:右位移运算符,双目操作符,左结合性,表示将运算符左侧的量每一个bit的值向右侧移动,左侧bit位补其符号位的值,如果是无符号型变量则补0,移动的位数为其右侧的量。原数值中最右侧的bit将丢失。例如12 >> 3表示将12中的每一个bit位0000 1100都向右移动3位,结果为0000 0001即1。

        关于位移运算还有很多需要注意的细节问题,例如左侧最高位数值溢出和补位问题在无符号型和有符号型变量中处理方式是不一样的,请参见《位移运算》

 

 

四、逗号运算符和逗号表达式

        逗号表达式比较简单,这是一个双目运算符,左结合性。它的作用是将多个不同的表达式连接在一起,形成一个表达式,整个表达式的值为逗号右侧的表达式的值。例如1 + 2, 3 + 4的结果为右侧表达式的值,结果为7。

        逗号表达式中的每一个子表达式都可以是另外一个逗号表达式,而多个表达式的值为最右侧表达式的值。例如:1 + 2, 2 + 3, 3 + 4, 4 + 5的结果为最右侧表达式4 + 5的结果,即9。

        另外,在逗号表达式和赋值运算符同时使用时需要注意,赋值运算符的优先级高于逗号表达式的优先级,所以

 

int a = 0;
a = 1, 2;
printf("%d\n", a);
a = (1, 2);
printf("%d\n", a);

1
2

 

        上面代码运行的结果为分别为1和2,因为赋值运算符的优先级高于逗号表达式的优先级,所以执行a = 1, 2;语句之后,a的值为1。而a = (1, 2);语句执行之后a的值为逗号表达式中右侧表达式的值2。因为括号的优先级高于“=”和“,”这两个运算符。

 

五、赋值运算符和自增自减运算

        赋值运算符为双目运算符,左结合性,赋值运算符的作用是将其右侧的内容赋于其左侧的变量,而整个表达式的值为其左侧量的值。例如:

 

a = 1;
b = 2;
c = a;
d = b + c;
e = printf("Hello World!\n");
f = e;

 

        上述程序中的操作都是将等号右侧的值赋与其右侧的值。

        我们再来看看复合赋值操作符与表达式。复合赋值操作符是将运算操作符与赋值操作符结合起来,先将左侧变量进行计算操作,然后将结果赋值给左侧变量:

+=:加等,先将左侧变量加上右侧的值,再将结果赋值给左侧变量。

-=:减等,先将左侧变量减去右侧的值,再将结果赋值给左侧变量。

*=:乘等,先将左侧变量乘以右侧的值,再将结果赋值给左侧变量。

/=:除等,先将左侧变量除以右侧的值,再将结果赋值给左侧变量。

%=:余等,先将左侧变量对右侧的值取余,再将结果赋值给左侧变量。

&=:与等,先将左侧变量和右侧的值做与运算,再将结果赋值给左侧变量。

|=:或等,先将左侧变量和右侧的值做或运算,再将结果赋值给左侧变量。

^=:与或等,先将左侧变量和右侧的值做与或运算,再将结果赋值给左侧变量。

<<=:左移等,先将左侧变量向左位移右侧的值的位数,再将结果赋值给左侧变量。

>>=:右移等,先将左侧变量向右位移右侧的值的位数,再将结果赋值给左侧变量。

        注意,这里面没有“反等”运算符,也就是先取反再赋值。因为在上面我们讲过 != 是一个关系运算符,表示“不等于”的意思。

        我们再来看一下赋值表达式与问号表达式的结合使用问题:

 

int a = 5, b = 7;
printf("%c\n", a = 1 - b > 7 ? 'A' : 'B');
printf("%c\n", (a = 1 - b) < 7 ? 'A' : 'B');

B
A

 

        需要注意的是:比较运算符 > 的优先级高于赋值运算符 = ,所以在上面例子中为赋值表达式加上括号和不加括号的结果是不一样的。关于操作符优先级的相关知识我们将在下一节中系统的学习。

 

        最后我们来看一下两个非常重要的运算符++和--。这两个运算符表示将变量的值增加1或减少1,例如:

int a = 3, b = 5; 
a++; 
b--;

        运行上面代码后,变量a的值自增1后变为4,而变量b的值自减1后也变为4。

        运算符++和--还有另外一种形式,就是先书写运算符再书写变量,例如:

 

int a = 3, b = 5; 
++a; 
--b;

        这段代码在运行之后,变量a的值自增1后变为4,而变量b的值自减1后也变为4。但从这两段代码中我们还看不出这两种写法的区别,它们的本质区别是:

表达式 变量++:在表达式执行之后,再将变量的值自增1。

表达式 ++变量:在表达式执行之前,先将变量的值自增1。

表达式 变量--:在表达式执行之后,再将变量的值自减1。

表达式 --变量:在表达式执行之前,将变量的值自减1。

        我们再来看这样一个说明它们不同的例子:

int a = 3, b;
b = a++;
printf("%d %d\n", a, b);

4 3

        先将变量a的值赋值给b,再对a进行自增,所以a和b的值分别为4、3。        

 

int a = 3, b;
b = ++a;
printf("%d %d\n", a, b);

4 4

        先变量a进行自增,再将变量a的值赋值给b,所以a和b的值都是4。   

    返回首页    返回顶部
  看不清?点击刷新

 

  Copyright © 2015-2018 问渠网 辽ICP备15013245号