一篇带你了解C语言--位操作详情

 更新时间:2021年08月12日 17:27:39   作者:Sauron7i  
这篇文章主要介绍了关于C语言位运算的简单示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

在C语言中,是可以单独操控变量中的位的。因为C在提供高级语言便利的同时,还能在为汇编语言所保留的级别上工作。

二进制数、位和字节

在我们日常生活中通常使用的十进制。

例如数字1234可以写成:

1 *10e3 + 2 * 10e2 + 3 * 10e1 + 4 * 10e0

这种方法是基于10的幂,所以称为以10为基底书写的。

那么以2为基底表示的数字就是二进制数。

例如:二进制数1111

1 * 2e3 + 1 * 2e2 + 1 * 2e1 + 1 * 2

转换成十进制就是:

1* 8+1* 4+1*2+1 = 15

二进制整数

C语言用字节表示存储系统字符集所需的大小,通常1字节为8位。

可以从左往右给这8位分别编号 7~0。在一字节中,编号是7的位被称为高阶位,编号为0的被称为低阶位,每一位的编号对应2的相应指数。

在这里插入图片描述

该字节能表示的最大的数字是把所有位设置为1:1111 1111,其值为255。最小值就是:0000 0000,其值为0。

所以1字节可以存储0~255范围内的数字总共256个值,在ASCII码中对应了256个状态。

unsigned char用1字节表示的范围是0~255,而signed char 用1字节表示范围是-128 ~ 127。

有符号整数

表示有符号数最简单的方式是用1位(高阶位)存储符号,剩下7位表示数字。
用这种符号量表示法,1000 0001表示 -1、0000 0001表示 1。其表示范围是 -127~127。这种方法的缺点是有两个0,+0和-0,有点浪费。

二进制补码方法避免了这个问题。以一字节为例:
二进制补码用1字节中的后7位表示0~127,高阶位设置为0.如果高阶位是1,表示的是负数。 假设一个值位组合为:1000 0000,无符号字节就表示的128,有符号字节表示-128。

要得到一个二进制补码的数的相反数,最简单的方法是反转每一位,然后加1。
1是0000 0001,-1就是 1111 1110 + 1,或 1111 1111。

二进制浮点数介绍

一个普通的十进制浮点数可以这样表示

0.234 = 2 /10 + 3 / 100 + 4 / 1000

从左往右各分母都是10的递增次幂。

那么在二进制浮点数中,使用2的幂作为分母,比如

.1011 = 1 / 2 + 0 / 4 + 1 / 8 + 1 / 16

八进制和十六进制

八进制以8为基底,用0~7表示数字。十六进制以16作为基底,用0 ~15表示数字。但没有单独的数表示10 ~ 15,所以用字母 A ~F表示。

在这里插入图片描述

3位二进制对应一位八进制

4位二进制对应一位十六进制

C按位运算符

C提供了按位逻辑运算符和移位运算符。

按位逻辑运算符

4个按位逻辑运算符都用于整形数据,包括char。

二进制反码或按位取反:~

一元运算符把1变为0,把0变为1。示例:

~(0001 1100)	//表达式
 (1110 0011)	// 结果值

需要注意的是该运算符不会改变之前变量的值,但确实创建了一个可以使用或赋值的新值。

按位与:&

二元运算符通过逐位比较两个运算对象生成一个新值。
对于每一个位,两个运算对象中相应的位都为1时,结果为1。示例:

(1001 1001) & (0011 1100)
//结果为
(0001 1000)

C有按位与和赋值结合的运算符:&=

val &= 0247
等价于
val = val & 0247

按位或:|

二元运算符|,对于每个位,如果两个运算对象中相应的位是1,结果为1。
示例:

(1001 1001) | (0111 0010)
结果为
(1111 1011)

同时C也有这样的运算符:|=

按位异或:^

二元运算符 ^,对于每一位,如果两个运算对象中相应的位一个为1,但不是两个为1,结果为1。
示例:

(1100 0001) ^ (0101 1011)
结果为
(1001 1010)

同时C也有这样的运算符: ^=

用法:掩码

所谓掩码指的是一些设置为开(1)或关(0)的位组合。
假设定义符号常量MASK为2,即(0000 0010),那么语句

val &= MASK

就是把val中除了1号位以外的所有位都设置为01号位的值不变。这个过程叫做使用掩码,掩码中的0隐藏了val中的其他位。
图解:

在这里插入图片描述

用法:打开位(设置位)

有时需要打开一个值中的特定位,而其他位保持不变。

val |= MASK;

把val的1号位设置为1,其他位不变。

因为|运算符,任何位与0组合结果为本身,任何位与1组合,结果都为1。

用法:关闭位(清空位)

和打开类似,有时需要再不影响其他位的情况下关闭指定的位。
假设要关闭变量val中的1号位,MASK只有1号位为1。即:

val = val & ~MASK;

由于MASK除1号位以外全为0,那~MASK除1号位以外全为1。再使用&,任何位与1组合都为本身,所以这条语句保持除1号位以外其他各位不变。
示例:

val ^= MASK;
(0000 1111) ^ (1011 0110)
结果为
(10111001)

用法:切换位

是指打开已关闭的位,或关闭已打开的位。可以使用按位异或运算符(^)切换位。

if ((val & MASK) == MASK)
	printf("...");

val中与MASK为1的位相对应的位都被切换了,MASK为0的位相对应的位不变。

用法:检查位的值

若检查val的某一位是否为1,可设置一个掩码刚好这个位为1.

若检查第二位,即:

MASK为(0000 0010)

程序可以这样写:

if ((val & MASK) == MASK)
	printf("...");

为了避免信息漏过边界,掩码至少要与其覆盖的值宽度相同。

移位运算符

左移:<<

左移运算符将其左侧运算对象每一位的值向左移动其右侧运算对象指定的位数。左侧运算对象移出左末端位的值丢失,用0填充空出的位置。
示例:

(1000 0110) << 2
结果为
(0001 1000)

可以使用左移赋值运算符(<<=)来更改变量的值。

int val = 1;	//0000 0001
val <<= 2;
结果为
0000 0100

右移:>>

右移运算符将其左侧运算对象每一位的值向右移动其右侧运算对象指定的位数。

对于无符号类型,用0填充空出的位置,对于有符号类型,结果取决于机器。

示例:>>=

int val = 16;	//0001 0000
val >>= 3;
结果为:
0000 0010

总结

本篇文章就到这里了,希望能给你带来帮助,也希望您能够多多关注脚本之家的更多内容!

您可能感兴趣的文章:

相关文章

  • 如何通过UltraEdit解析BMP文件内部结构(BMP位图基础)

    如何通过UltraEdit解析BMP文件内部结构(BMP位图基础)

    我们先打开画图随便画一幅图并采用24位bmp图像格式保存,就得到了一张24位真彩色的位图,下面我们来详细分析bmp位图的各个组成部分,感兴趣的朋友跟随小编一起看看吧
    2021-08-08
  • C++实现停车场管理系统的示例代码

    C++实现停车场管理系统的示例代码

    停车场管理系统就是模拟停车场进行车辆管理的系统,该系统分为汽车信息模块,用户使用模块和管理员用户模块,本文将用C++实现这一简单的系统,希望对大家有所帮助
    2023-04-04
  • win32使用openfilename浏览文件窗口示例

    win32使用openfilename浏览文件窗口示例

    这篇文章主要介绍了使用win32 API打开浏览文件窗口,使用OPENFILENAME结构体来实现这个功能,需要的朋友可以参考下
    2014-02-02
  • C++中最常用的容器用法与排序实例

    C++中最常用的容器用法与排序实例

    C++ 中容器被定义为:在数据存储上,有一种对象类型,它可以持有其它对象或指向其它对像的指针,这种对象类型就叫做容器,这篇文章主要给大家介绍了关于C++中最常用的容器用法与排序的相关资料,需要的朋友可以参考下
    2021-08-08
  • C++11 并发指南之std::thread 详解

    C++11 并发指南之std::thread 详解

    这篇文章主要介绍了C++11 并发指南之std::thread 详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-02-02
  • C语言修炼之路初识分支句 循环助本心上篇

    C语言修炼之路初识分支句 循环助本心上篇

    现实生活中我们经常需要根据不同的条件做出不同的选择。程序设计中也需要根据条件来选择不同的程序进行处理,这称之为分支结构,当条件表达式不存在时,它被假设为真。您也可以设置一个初始值和增量表达式,一般情况下,C 程序员偏向于使用 for(;;) 结构来表示一个无限循环
    2022-03-03
  • C语言链表实现贪吃蛇游戏

    C语言链表实现贪吃蛇游戏

    这篇文章主要为大家详细介绍了C语言链表实现贪吃蛇游戏源码,适合C语言入门者学习阅读,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-10-10
  • 带头结点的链表的基本操作(超详细)

    带头结点的链表的基本操作(超详细)

    链表是一种动态分配空间的存储结构,能更有效地利用存储空间,通过对单链表基本操作的代码实现,我深刻领悟到以“指针”指示元素的后继,在插入或删除元素时不需要移动元素
    2023-07-07
  • C语言实现井字棋详解

    C语言实现井字棋详解

    这篇文章主要为大家介绍了C语言如何实现井字棋,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2021-11-11
  • C语言实现支持动态拓展和销毁的线程池

    C语言实现支持动态拓展和销毁的线程池

    这篇文章主要为大家介绍了C语言实现支持动态拓展和销毁的线程池,感兴趣的小伙伴们可以参考一下
    2016-01-01

最新评论