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) 位段可以在数值表达式中引用,它会被系统自动地转换成整型数。

相关文章
|
17天前
|
C语言
C语言------程设设计入门
这篇文章是C语言程序设计的入门教程,涵盖了C程序的实现过程、VC集成开发环境的使用、基本数据类型的使用、格式控制字符的作用,以及通过示例代码演示了如何使用printf()函数输出不同类型的数据。
C语言------程设设计入门
|
29天前
|
NoSQL Java 编译器
C语言从入门到精通该怎样学?
持续学习与实践:编程是一门需要不断学习和实践的技能,要保持对新技术和新知识的敏感性,并持续进行编程实践。
31 1
|
2月前
|
存储 Java C语言
【C语言入门】初识C语言:掌握编程的基石
【C语言入门】初识C语言:掌握编程的基石
42 4
【C语言入门】初识C语言:掌握编程的基石
|
2月前
|
存储 Java 程序员
【C语言入门】C语言入门:探索编程世界的基础概念
【C语言入门】C语言入门:探索编程世界的基础概念
53 2
|
2月前
|
前端开发 C语言 C++
C语言入门02---环境搭建
C语言入门02---环境搭建
|
2月前
|
编译器 C语言 C++
C++从遗忘到入门问题之C++持从C语言的过渡问题如何解决
C++从遗忘到入门问题之C++持从C语言的过渡问题如何解决
|
3月前
|
存储 Web App开发 算法
c语言的简单入门
熟悉c语言(简单入门)
|
3月前
|
JavaScript C语言
|
3月前
|
存储 人工智能 Java
|
3月前
|
C语言
C语言中的位运算详解
C语言中的位运算详解
34 0