内容正文:
第10章 位运算
本章内容
10.1位运算符和位运算
10.2位段
10.3综合案例
10.1位运算符和位运算
补码
在计算机系统中,数值一律用补码来表示
已知数计算补码
正数的补码是它本身
负数的补码是将符号位定义为1,其余位为该数绝对值的二进制按位取反,然后整个数加1
-7的补码 =11111001
已知补码计算数
如果补码的符号位为0,表示是一个正数,所以补码就是该数本身
如果补码的符号位为1,表示是一个负数,求其数值的操作过程为:除符号位外,其余各位取反,然后再整个数加1
补码的补码既是数本身
位运算符
按位与运算符&
运算规则为:
0&0=0,0&1=0,1&0=0,1&1=1
计算9&5。由于9的二进制补码为00001001,5的二进制补码为00000101,因此9&5可写为如下算式:00001001&00000101,结果为00000001,故9&5=1
按位或运算符|
运算规则为:
0|0=0,0|1=1,1|0=1,1|1=1
9|5可写算式如下: 00001001|00000101,结果为00001101 ,即十进制的13
按位异或运算符^
运算规则为:
0^0=0,0^1=1,1^0=1,1^1=0
9^5可写算式如下:00001001^00000101,结果为00001100,即十进制的12
求反运算符~
运算规则为:
~0=1,~1=0
~9的运算为:~(0000000000001001)的结果为:1111111111110110。
左移运算符<<
把<<左边的运算数的各二进位全部左移若干位,由<<右边的数指定移动的位数,高位丢弃,低位补0
a<<4指把a的各二进位向左移动4位。如a=00000011(十进制3),左移4位后为00110000(十进制48),即3*24,a=00000101(十进制5);a<<3结果为00101000为40,即5*23。
右移运算符>>
把>>左边的运算数的各二进位全部右移若干位, >>右边的数指定移动的位数
设 a=15,a>>2表示把000001111右移为00000011(十进制3),即15/22;a=35,a>>3表示把000100011右移为00000100(十进制4),即35/23
10.2位段
位段和位段变量
位段的定义和位段变量的说明与结构定义相仿,其形式为:
struct 位段结构名
{ 位段列表 };
其中位段列表的形式为:
类型说明符 位段名:位段长度
位段变量的说明与结构体变量说明的方式相同
例如:
struct bs
{
int a:8;
int b:2;
int c:6;
};
位段的定义注意事项
一个位段必须存储在同一个存储单元(即字)中,不能跨两个单元
例如:
struct bs
{
unsigned a:6;
unsigned :0; /*无名位段,表示下一位段从下一单元边界开始*/
unsigned b:4; /*从下一单元开始存放*/
unsigned c:4;
}
位段的定义注意事项
由于位段不允许跨两个单元,因此位段的长度不能大于一个单元的长度
位段可以无位段名,这时它只用作填充或调整位置
例如:
struct k
{
int a:1;
int :2; /*该2位不能使用*/
int b:3;
int c:2;
};
位段的定义注意事项
位段无地址,不能对位段进行取地址运算
位段可以以%d,%o和%x格式输出
位段若出现在表达式中,将被系统自动转换成整数
位段的使用
其一般形式为:
位段变量名.位段名
main()
{
struct bs
{
unsigned a:1;
unsigned b:3;
unsigned c:4;
} bit,*pbit;
bit.a=1;
bit.b=7;
bit.c=15;
printf("%d,%d,%d
",bit.a,bit.b,bit.c);
pbit=&bit;
pbit->a=0;
pbit->b&=3;
pbit->c|=1;
printf("%d,%d,%d
",pbit->a,pbit->b,pbit->c);
}
10.3综合案例
【例10.2】输入一个整数,判断该数是奇数还是偶数,并输出相应的提示。要求用位运算判断。
分析:
输入整数n。
由于所有奇数的二进制位的最低位均为1,偶数的二进制最低位均为0,因此可以将数n与1进行与运算,如果结果为1,则是奇数,否则是偶数。
#include "stdio.h"
main()
{
int n;
printf("
Please input n:");
sc