C语言入门系列之12.位运算(下)

简介: 位运算是指按二进制位进行的运算,这是因为在系统软件中,常要处理二进制位的问题。

右移运算符>>

右移运算符是a>>2表示将a的各二进制位右移2位,移到右端的低位被舍弃,对无符号数,高位补0。

例如a=017时,a的值用二进制形式表示为00001111, 舍弃低2位11,得到a >> 2 == 00000011。

可以得到:

右移一位相当于除以2,右移n位相当于除以2n。

有关符号位的注意事项如下:

对无符号数,右移时左边高位移入0;

对于有符号的值,如果原来符号位为0(该数为正),则左边也是移入0;

如果符号位原来为1(即负数),则左边移入0还是1,要取决于所用的计算机系统,有的系统移入0,有的系统移入1。

移入0的称为逻辑右移, 即简单右移;

移入1的称为算术右移。

例如,a的值是十进制数-2:

a = 1111 1110(用二进制形式表示);

无符号数:a>>1 = 0111 1111 (逻辑右移时);

有符号数:a>>1 = 1111 1111 (算术右移时)。

练习如下:

#include <stdio.h>
int main(){
  unsigned char a = -2;
  char b = -2;
  a = a >> 1;
  b = b >> 1;
  printf("a = %d\nb = %d\n", a, b);
  return 0;
}

打印:

a = 127
b = -1

显然,C语言对于有符号数和无符号数的处理是不同的。

位运算赋值运算符

位运算符与赋值运算符可以组成复合赋值运算符。

例如: &=、|=、>>=、<<=、^=。

所以,a &= b相当于a = a & ba <<= 2相当于a = a << 2

二、位运算举例

练习:

取一个字符型变量a从右端开始的2-5位。

实现思路:

(1)先使a右移2位a >> 2,目的是使要取出的那几位移到最右端;

(2)设置一个低4位全为1,其余全为0的数,即~(~0 << 4);

(3)将(1)、(2)进行&运算,(a >> 2) & ~(~0 << 4)。

代码如下:

#include <stdio.h>
int main(){
  char a, b, c, d;
  printf("Please input the number:\n");
  scanf("%d", &a);
  b = a >> 2;
  c = ~(~0<<4);
  d = b & c;
  printf("%d\n");
  return 0;
}

打印:

Please input the number:
37
9

练习:

要求将a进行右循环移位,如下:

2345_image_file_copy_88.jpg

代码如下:

#include <stdio.h>
int main(){
  unsigned a, b, c, d;
  int n;
  printf("Please input the number:\n");
  scanf("%d", &a);
  printf("Please enter the number of digits to be moved:\n");
  scanf("%d", &n);
  b = a << (sizeof(char) * 8 - n);
  c = a >> n;
  d = b | c;
  printf("result = %d\n", d);
  return 0;
}

打印:

Please input the number:
25
Please enter the number of digits to be moved:
2
result = 1606

三、位段

信息的存取一般以字节为单位,但有时存储一个信息不必用一个或多个字节。

例如,真或假用0或1表示,只需1位即可。

在计算机用于过程控制、参数检测或数据通信领域时,控制信息往往只占一个字节中的一个或几个二进制位,常常在一个字节中放几个信息。

C语言允许在一个结构体中以位为单位来指定其成员所占内存长度,这种以位为单位的成员称为位段或称位域(bit field),利用位段能够用较少的位数存储数据。

如下:

struct  packed_data{
    unsigned a:2;
    unsigned b:6;
    unsigned c:4;
    unsigned d:4;
    int 1;
} data; 

位段的定义和引用的说明:

(1)位段成员的类型必须指定为unsigned或int类型。

(2)若某一位段要从另一个字开始存放,可用以下形式定义:

unsigned a:1;
unsigned b:2;   // 一个存储单元       
unsigned :0;
unsigned c:3; // 另一存储单元  

a、b、c应连续存放在一个存储单元中,由于用了长度为0的位段,其作用是使下一个位段从下一个存储单元开始存放。因此,只将a、b存储在一个存储单元中,c另存在下一个单元(存储单元可能是一个字节,也可能是2个字节,视不同的编译系统而异)。

(3) 一个位段必须存储在同一存储单元中,不能跨两个单元;

如果第一个单元空间不能容纳下一个位段,则该空间不用,而从下一个单元起存放该位段。

(4) 可以定义无名位段。

(5) 位段的长度不能大于存储单元的长度,也不能定义位段数组。

(6) 位段可以用整型格式符输出。

(7) 位段可以在数值表达式中引用,它会被系统自动地转换成整型数。

相关文章
|
1月前
|
人工智能 C语言
【C语言必知必会| 第七篇】循环结构入门,这一篇就够了
【C语言必知必会| 第七篇】循环结构入门,这一篇就够了
14 0
|
1月前
|
Serverless C语言
【C语言必知必会 | 第五篇】选择结构入门,这一篇就够了
【C语言必知必会 | 第五篇】选择结构入门,这一篇就够了
19 0
|
1月前
|
存储 编译器 C语言
【C语言必知必会 | 第三篇】顺序结构入门,这一篇就够了
【C语言必知必会 | 第三篇】顺序结构入门,这一篇就够了
16 0
|
2月前
|
C语言
c语言编程练习题:7-10 算术入门之加减乘除
对于输入的两个整数,按照要求输出其和差积商。
18 0
|
4天前
|
C语言
C语言自增减、逻辑运算、位运算、位移运算及三目运算操作
C语言自增减、逻辑运算、位运算、位移运算及三目运算操作
7 0
|
27天前
|
存储 编译器 C语言
一篇带你玩转C语言指针:从入门到精通
一篇带你玩转C语言指针:从入门到精通
|
1月前
|
存储 编译器 C语言
【C语言必知必会| 第十篇】指针入门,这一篇就够了
【C语言必知必会| 第十篇】指针入门,这一篇就够了
19 0
|
1月前
|
存储 Unix 编译器
【C语言必知必会 | 第一篇】C语言入门,这一篇就够了
【C语言必知必会 | 第一篇】C语言入门,这一篇就够了
19 0
|
1月前
|
C语言 定位技术 存储
【C语言基础入门】二级指针、一维数组与指针、二维数组与指针
【C语言基础入门】二级指针、一维数组与指针、二维数组与指针
【C语言基础入门】二级指针、一维数组与指针、二维数组与指针
|
2月前
|
算法 C语言
算法竞赛入门【码蹄集新手村600题】(MT1280-1300)C语言
算法竞赛入门【码蹄集新手村600题】(MT1280-1300)C语言
43 0