欢迎访问文稿网!

逻辑运算中各运算符的优先顺序

范文之家 分享 时间: 加入收藏 我要投稿 点赞

逻辑运算中各运算符的优先顺序

    2.4.5 位运算符和位表达式

    位运算是指进行二进制位的运算。在C语言中,位运算符有位逻辑运算符和移位运算符。如果对汇编语言有了解的读者,可以跳过本小节。

    为简单起见,假设内存的一个存储单元占用一个字节,一个整数占用2个字节。读者可以自行推广到其他情况(如内存的一个存储单元占用一个字或双字等)。

    1.字节和位

    内存是以字节为单位的连续的存储空间,每个内存单元有一个唯一的编号,即地址。

    一个字节由8个二进制位(bit)组成,其中最右边的一位称为“最低位”,最左边的一位称为“最高位”。每一个二进制位的值是0或1。

    2.数值的编码表示

    在计算机内表示数值的时候,以最高位作为符号位,最高位为0表示数值为正,为1表示数值为负。表示数值,可采用不同的编码方法,一般有:原码、反码和补码。

    1)原码

    用最高位作为符号位来表示数的符号:为0代表正数,为1代表负数,其余各位代表数值本身的绝对值(以二进制表示)。

    例如:

    +10的原码是:0000000000001010

    img65

    +0的原码是:0000000000000000

    −0的原码是:1000000000000000

    +0和−0表示的是同一个数0,而在内存中却有两个不同的表示。由于0的表示方法不唯一,不适合计算机的运算,所以在计算机内部一般不使用原码来表示数。

    2)反码

    正数的反码与原码相同,如+10的反码也是0000000000001010。

    负数的反码是:原码符号位外仍为1,其他各位取反。如−10的反码是1111111111110101。

    +0的反码是:0000000000000000

    −0的反码是:1111111111111111

    同样,0的表示不唯一。所以在计算机内部一般也不使用反码来表示数。

    3)补码

    正数的补码与原码相同。如+10的补码同样是0000000000001010。而负数的补码是:除最高位仍为1外,原码的其余各位求反,最后再加1。例如,−10的原码是:1000000000001010,求反(除最高位外)后,得到1111111111110101,再加1,结果是1111111111110110。或者说,负数的补码是其反码加1。

    +0的补码是:0000000000000000

    −0的补码是:1111111111111111

    img66

    用补码形式表示数值0时,是唯一的,都是0000000000000000。

    计算机通常都是以补码形式存放数。因为采用补码形式不仅数值表示唯一,而且能将符号位与其他位统一处理。实际上采用补码,在计算机中也可以使减法变为加法,为硬件实现减法提供方便。

    3.位逻辑运算符与位逻辑表达式

    位逻辑运算符有4种:

    & (按位与);∣(按位或);~ (按位取反);^ (按位异或)。

    按位取反~是单目运算符,其余3个是双目运算符。

    位逻辑运算符按二进制位逐位地进行运算,相邻位之间不发生联系,即没有“进位”、“借位”等问题,所以称为位逻辑运算符。对参加逻辑运算的操作数,编译程序以其二进制形式表达。

    位逻辑运算符的作用如表2.4.2所示。

    

    表2.4.2 位逻辑运算符的作用

    img67

    1)按位与运算符&

    按位与的运算规则是:如果两个相应的二进制位都为1,则该位的结果为1,否则为0。

    即

    1 & 1= 1 1 & 0= 0 0 & 1= 0 0 & 0= 0

    例如:

      unsigned int i=4988, j=63286;

    i为

      0001001101111100 (即0x137C或011574)

    j为

      1111011100110110 (即0xF736或0173466)

    则i&j的运算为

      0001001101111100

    img68

    &运算经常用于将特定位清零(屏蔽)。例如i的值为1000000000100110,j的值为1111111111100000,则i&j的结果是1000000000100000,相当于将i的低5位屏蔽,高11位不变。可见,若要将某数的某些二进制位取出来,可以将其他位清零,将需要取出来的位同1做按位与即可。

    注意:如果两个长度不同的数据(例如long型和int型)进行位运算时(如i&j,i 为long 型,j为int型),系统会将二者按右端对齐。如果j为正数,则左侧16位补满0;如果j为负数,则左侧16位补满1;如果j为无符号整型数,则左侧16位也补满0。

    2)按位或运算符|

    按位或的运算规则是:两个相应的二进制位只要有一个为1,则该位的结果为1,否则为0。即

      1∣1= 1, 0∣1= 1,  1∣0= 1,  0∣0= 0

    以上面的例子为例,i|j的结果为

      0001001101111100

    img69

    按位或|运算经常用于将一个数据的某些位定值为1。例如要想使一个数m的低4位改为1,只需将m与017进行按位或即可。

    3)按位异或运算符^

    按位异或的运算规则是:如果参与运算的两个相应的二进制位相同,则该位的结果为0,否则为1。即

      1^1 = 0,0^0 = 0,1^0 = 1,0^1 = 1

    仍以上面的例子为例,i^j的结果为

      0001001101111100

    img70

    按位异或^运算符能使特定位按位变反,方法是将这些特定位与1异或。例如i的值为1000000000100110,j的值为1111111111100000,则i^j的结果是0111111111000110。凡是与1异或的位都变反了,而与0异或的位不变。

    4)按位取反运算符~

    将一个二进制数按位取反,即将0变为1,1变为0。即

    ~1 = 0,~0 = 1

    注意: ~0x7 (即~07或~7)在16位机上是:

    1111111111111000  (即0xFFF8或0177770)而在32位机上是:

    11111111111111111111111111111000 (即0xFFFFFFF8或037777777770)

    所以,在C程序中,最好采用~0x7或~07来表示7的逻辑取反,而不要采用形如

      0xFFF8、0177770或0xFFFFFFF8、037777777770

    等表达式。主要原因是:前一种表达式与机器硬件特性无关,从而保证了程序的可移植性。

    各个位逻辑运算符的优先级关系是:~最高,其余3个运算符的优先级从高到低依次是&、^、|,但三者都高于逻辑运算符而低于关系运算符。使用时注意加括号。例如:

      n =((i&j)|k)

    由位逻辑运算符和操作数构成的表达式称为位逻辑表达式。位逻辑表达式中操作数都应该是整型量或字符型量,不允许是浮点型量。

    位逻辑运算符与逻辑运算符之间的区别:

    ①位逻辑运算符是针对二进制位的,而逻辑运算符是针对整个表达式的;位逻辑运算符要计算表达式的具体数值,而逻辑运算符只判断表达式的真与假。

    ②位逻辑运算符&、|和 ^的两个操作数是可交换的;而逻辑运算符&&和||的两个操作数是不可交换的,并且它们严格执行自左至右的运算。例如:

      40&8  结果是8    40&&8  结果是1 (真)

      40|8  结果是40   40||8   结果是1 (真)

      0||x  结果是1(若x≠0) 或0(若x= 0)

      0&&x  结果是0,其中x是任意表达式

    位逻辑运算符通常用于与硬件相应的程序中,如设备驱动程序,对表示状态字中的某些位进行测试、设置和屏蔽等。

    4.移位运算符和移位表达式

    C语言中实现移位功能的运算符有两个:左移<<和 右移>>。

    它们都是双目运算符,并且要求两个操作数都是整型数据。由移位运算符和操作数构成的表达式称为移位表达式。

    1)左移位运算符<<

    它的一般使用形式是:

      整型变量<<表达式

    其中,表达式表示移位的位数。它的功能是:将变量的值(以二进制形式表示)向左移动n位,n值由表达式确定(该值必须是正整数)。整个表达式的值是变量移位后的值,而变量本身值不变。

    例如,m=0000000000001011,那么移位表达式

    m<<3的结果是0000000001011000,即将m的各二进制位全部向左移3位,右边空出的位补0,而左边溢出的位被丢弃不管。

    在容许的范围内,对于正数,利用左移位运算可扩大原数的倍数,左移1位扩大2倍,左移2位扩大4倍,即可实现被移对象乘以n2功能。例如, m的值是11,左移3位后,结果值是88,等于11×2³ =11×8=88。

    2)右移运算符>>

    它的一般使用形式是:

      变量>>表达式

    其中,表达式表示表示移位的位数。它的功能是:将变量的值(以二进制形式表示)向右移n位,n的值由表达式确定(该值必须是正整数)。整个表达式的值是变量移位后的值,而变量本身值不变。

    例如,m=0000000000001000,那么,移位表达式

      m>>2

    的结果是0000000000000010,即:将m的各二进制位全都向右移2位,右边溢出的位被丢弃,而左边空出的位(在本例情况下)补0。

    对于正数,右移一位相当于该数除以2,右移n位相当于该数除以n2。

    在右移时,要注意符号位问题。如果移位对象是无符号数,那么右移时左边空出来的位全以0填充,这种方式称为逻辑右移方式;如果移位对象是有符号数,当移位对象是正数(符号位为0)时,左边空位用0填充;当移位对象是负数(符号位为1)时,左边空位是补0还是补1,要取决于编译系统。有的系统按逻辑右移方式(即补0)处理,有的系统则按算术右移方式(即补1)处理。

221381
领取福利

微信扫码领取福利

微信扫码分享