【C语言】移位操作详解 - 《凌波微步 ! 》

目录

  • C语言移位操作 (Bitwise Shift Operators) 详解
    • 1. 移位操作符概述
      • 1.1 左移操作符 (`<<`)
      • 1.2 右移操作符 (`>>`)
    • 2. 使用示例
      • 2.1 左移操作符示例
      • 2.2 右移操作符示例
      • 2.3 有符号和无符号右移
    • 3. 注意事项
      • 3.1 超出位数范围的移位
      • 3.2 移位操作的性能
    • 4. 移位操作的应用
      • 4.1 快速乘法和除法
      • 4.2 位标志操作
      • 4.3 数据打包和解包
    • 5. 总结
    • 6. 参考文献
    • 7. 结束语

C语言移位操作 (Bitwise Shift Operators) 详解

移位操作符在C语言中用于将二进制位向左或向右移动。移位操作符有两种:左移操作符 (<<) 和右移操作符 (>>)。这些操作符在处理位级别的数据操作时非常有用,如图像处理、加密算法和嵌入式系统开发。本文将详细介绍C语言中的移位操作,包括其基本概念、使用方法、示例代码和注意事项。

1. 移位操作符概述

C语言提供了两个移位操作符:

  1. 左移操作符 <<:将位模式向左移动指定的位数。
  2. 右移操作符 >>:将位模式向右移动指定的位数。

1.1 左移操作符 (<<)

左移操作符将二进制位模式向左移动指定的位数,右边填充0。其效果相当于将数乘以2的n次方。

int a = 5; // 二进制: 0000 0101
int b = a << 1; // 左移1位: 0000 1010 (结果为10)
int c = a << 2; // 左移2位: 0001 0100 (结果为20)

1.2 右移操作符 (>>)

右移操作符将二进制位模式向右移动指定的位数,左边填充符号位(对于有符号整数)或0(对于无符号整数)。其效果相当于将数除以2的n次方。

int a = 20; // 二进制: 0001 0100
int b = a >> 1; // 右移1位: 0000 1010 (结果为10)
int c = a >> 2; // 右移2位: 0000 0101 (结果为5)

2. 使用示例

2.1 左移操作符示例

左移操作符将数值的二进制位向左移动,右边补0。

#include <stdio.h>int main() {int a = 5; // 二进制: 0000 0101int b = a << 1; // 左移1位: 0000 1010 (结果为10)int c = a << 2; // 左移2位: 0001 0100 (结果为20)printf("a << 1 = %d\n", b); // 输出: 10printf("a << 2 = %d\n", c); // 输出: 20return 0;
}

2.2 右移操作符示例

右移操作符将数值的二进制位向右移动,对于无符号整数左边补0,对于有符号整数左边补符号位。

#include <stdio.h>int main() {int a = 20; // 二进制: 0001 0100int b = a >> 1; // 右移1位: 0000 1010 (结果为10)int c = a >> 2; // 右移2位: 0000 0101 (结果为5)printf("a >> 1 = %d\n", b); // 输出: 10printf("a >> 2 = %d\n", c); // 输出: 5return 0;
}

2.3 有符号和无符号右移

有符号整数右移操作时,会保留符号位,即最高位。如果是负数,则最高位为1。

#include <stdio.h>int main() {int a = -20; // 二进制: 1110 1100 (以8位表示,实际存储可能更多)int b = a >> 1; // 右移1位: 1111 0110 (结果为-10)int c = a >> 2; // 右移2位: 1111 1011 (结果为-5)printf("a >> 1 = %d\n", b); // 输出: -10printf("a >> 2 = %d\n", c); // 输出: -5unsigned int ua = 20; // 二进制: 0001 0100unsigned int ub = ua >> 1; // 右移1位: 0000 1010 (结果为10)unsigned int uc = ua >> 2; // 右移2位: 0000 0101 (结果为5)printf("ua >> 1 = %u\n", ub); // 输出: 10printf("ua >> 2 = %u\n", uc); // 输出: 5return 0;
}

3. 注意事项

3.1 超出位数范围的移位

如果移位的位数超出了变量类型的位数范围,结果是不确定的。例如,对于一个32位的整数,移位操作数大于或等于32时,行为未定义。

int a = 5;
int b = a << 32; // 行为未定义

3.2 移位操作的性能

移位操作通常比乘法和除法更高效,因为它们可以直接在硬件层面进行操作。但是需要注意的是,滥用移位操作可能会降低代码的可读性。

4. 移位操作的应用

移位操作在很多场景下都有应用,以下是一些常见的应用场景:

4.1 快速乘法和除法

左移操作可以用来快速乘以2的幂,右移操作可以用来快速除以2的幂。

int a = 5;
int b = a << 3; // 相当于 a * 2^3 = 5 * 8 = 40
int c = a >> 1; // 相当于 a / 2^1 = 5 / 2 = 2

4.2 位标志操作

移位操作常用于位标志的操作。例如,可以使用移位操作设置、清除或检测某个位。

#define FLAG1 0x01 // 0000 0001
#define FLAG2 0x02 // 0000 0010int flags = 0;
flags |= FLAG1; // 设置FLAG1
flags &= ~FLAG2; // 清除FLAG2
int is_flag1_set = flags & FLAG1; // 检测FLAG1是否设置

4.3 数据打包和解包

移位操作可用于将多个数据打包到一个变量中或从一个变量中解包数据。

unsigned char high = 0xAB; // 高字节
unsigned char low = 0xCD; // 低字节
unsigned short combined = (high << 8) | low; // 打包高低字节: 0xABCDhigh = (combined >> 8) & 0xFF; // 解包高字节: 0xAB
low = combined & 0xFF; // 解包低字节: 0xCD

5. 总结

移位操作符是C语言中非常重要的工具,提供了高效的位级操作方法。理解和正确使用移位操作符,对于编写高性能和高效能的程序至关重要。本文详细介绍了左移和右移操作符的使用方法、应用场景及注意事项,希望对您理解和使用C语言移位操作有所帮助。

6. 参考文献

  1. Kernighan, B. W., & Ritchie, D. M. (1988). The C Programming Language (2nd ed.). Prentice Hall.
  2. ISO/IEC. (1999). ISO/IEC 9899:1999. Programming Languages – C.
  3. ISO/IEC. (2024). ISO/IEC DIS 9899. Programming Languages – C.
  4. Harbison, S. P., & Steele, G. L. (2002). C: A Reference Manual (5th ed.). Prentice Hall.

7. 结束语

  1. 本节内容已经全部介绍完毕,希望通过这篇文章,大家对C语言中的移位操作有了更深入的理解和认识。
  2. 感谢各位的阅读和支持,如果觉得这篇文章对你有帮助,请不要吝惜你的点赞和评论,这对我们非常重要。再次感谢大家的关注和支持

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/46844.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PostgreSQL使用(二)

说明&#xff1a;本文介绍PostgreSQL的DML语言&#xff1b; 插入数据 -- 1.全字段插入&#xff0c;字段名可以省略 insert into tb_student values (1, 张三, 1990-01-01, 88.88);-- 2.部分字段插入&#xff0c;字段名必须写全 insert into tb_student (id, name) values (2,…

【后端开发实习】用Redis实现消息队列邮件发送

简介 用Resi本身封装的方法相比于调redis-smq库&#xff0c;实现方式就要简单朴素很多&#xff1a; 调用redis本身的List数据结构的Lpush实现消息的进队。用Redis的List数据结构的brpop方法实现消息的出队。将出队消息通过邮件方法发送给指定的用户。 生动形象理解就是用redi…

《javeEE篇》--多线程(1)

进程 在讲线程之前我们先来简单了解一下进程 什么是进程 进程是操作系统对一个正在运行的程序的一种抽象&#xff0c;又或者说&#xff0c;可以把进程看作程序的一次运行过程(通俗的讲就是跑起来的程序)。 而且在操作系统内部&#xff0c;进程是资源分配的基本单位 PCB P…

python实例练习00001:使用正则表达式获取文件内容

print(Hello World!) import re try:file = input(enter the file :)with open(file, r) as f:data = f.read() except FileNotFoundError:print(fthe file {file} does not exists:)# 定义正则表达式 pattern = r"num (\d+) name (\w+) class (\d+) age (\d+)" # 使…

Python 是一种用途广泛的编程语言,应用于各个领域

1. 网络和互联网开发: Python 拥有丰富的框架和库&#xff0c;使其成为 Web 开发的理想选择。 框架: Django 和 Pyramid 用于构建复杂的 Web 应用。Flask 和 Bottle 则适合轻量级应用和 API。 库: Python 标准库支持处理 HTML、XML、JSON 和电子邮件。此外&#xff0c;还有强大…

内容长度不同的div如何自动对齐展示

平时我们经常会遇到页面内容div结构相同页&#xff0c;这时为了美观我们会希望div会对齐展示&#xff0c;但当div里的文字长度不一时又不想写固定高度&#xff0c;就会出现div长度长长短短&#xff0c;此时实现样式可以这样写&#xff1a; .e-commerce-Wrap {display: flex;fle…

轻量级自适用商城卡密发卡源码(可运营)

一款全开源非常好看的发卡源码。轻量级自适应个人自助发卡简介&#xff0c;这是一款二次开发的发卡平台源码修复原版bug,删除无用的代码。所有文件全部解密&#xff0c;只保留后台版权信息内容。大家放心使用&#xff0c;可以用于商业运营。轻量级自适应个人自助发卡。 源码下…

R语言学习笔记7-列表

R语言学习笔记7-列表 列表(list)介绍空列表包含元素的列表嵌套列表访问列表元素添加新元素删除元素修改元素使用for循环遍历列表使用lapply遍历和操作列表使用sapply简化列表操作合并列表检查元素是否存在列表长度和名称操作将列表转换为其他数据类型列表与环境的交互列表在函数…

写python代码,怎么用工厂模式思维设计接口?

接口的好处 接口就是抽象方法&#xff0c;用来设计后架构&#xff0c;后端开发者和客户端调用者都可以使用这个接口规则同步写代码&#xff0c;客户端调用者&#xff08;app、网页甚至时自动化接口测试&#xff09;不用担心后端对接口的实现细节具体是什么样子的。直接去调用就…

QTimer::singleShot()

QTimer::singleShot() 是 Qt 框架中的一个静态函数&#xff0c;用于创建一个单次定时器事件。它的作用是在指定的时间间隔之后触发一个单次的定时器事件&#xff0c;然后停止定时器。 其函数原型为&#xff1a; static void QTimer::singleShot(int msec, const QObject *rec…

获取欧洲时报中国板块前新闻数据(多线程版)

这里写目录标题 一.数据获取流程二.获取主页面数据并提取出文章url三.获取文章详情页的数据并提取整体代码展示 一.数据获取流程 我们首先通过抓包就能够找到我们所需数据的api 这里一共有五个参数其中只有第一个和第五个参数是变化的第一个参数就是第几页第五个是一个由时…

STM32学习和实践笔记(40):DS18B20温度传感器实验

1.DS18B20介绍 DS18B20 是由 DALLAS 半导体公司推出的一种的“一线总线(单总线)”接口的温度传感器。与传统的热敏电阻等测温元件相比,它是一种新型的体积小、适用电压宽、与微处理器接口简单的数字化温度传感器。 DS18B20温度传感器具有如下特点: 1、适应电压范围更宽,…

Spring 的核心注解

Spring框架使用了一系列的核心注解来支持其功能&#xff0c;以下是一些最常用的Spring注解&#xff1a; 1. Component: - 用于标记类为Spring组件&#xff0c;Spring容器会管理这些类的对象。 2. Service: - 特定于服务层的Component注解&#xff0c;表示一个服务组件。…

Qt 多窗体、复用窗口的使用

1.继承自QWidge的窗口的呈现&#xff0c;作为tabPage呈现&#xff0c;作为独立窗口呈现 2.继承自QMainWindow的窗口的呈现&#xff0c;作为abPage呈现&#xff0c;作为独立窗口呈现 1. 继承自QWidge的窗口的呈现 1.1 作为tabPage呈现 void MutiWindowExample::on_actWidgetI…

分项加载页面统计数据

我们在做一个统计页面时&#xff0c;原来大约有1000万左右的数据进行查询&#xff0c;还可以接受&#xff0c;但是随着业务量的增大&#xff0c;目前有3000多万的数据来统计&#xff0c;一次统计出查询结果就很慢很慢&#xff0c;有时候会出现超时异常。 为了解决这个问题&…

云计算数据中心(一)

目录 一、云数据中心的特征二、云数据中心网络部署&#xff08;一&#xff09;改进型树结构&#xff08;二&#xff09;递归层次结构&#xff08;三&#xff09;光交换网络&#xff08;四&#xff09;无线数据中心网络&#xff08;五&#xff09;软件定义网络 一、云数据中心的…

Briefcase:将Python项目转化为多平台应用的利器

文章目录 引言官网链接原理基础使用安装 Briefcase初始化项目构建应用创建应用包 高级使用应用程序配置和定制化与打包工具的集成自动处理依赖关系 优缺点优点缺点 总结 引言 Briefcase 是一个功能强大的工具&#xff0c;主要用于将 Python 项目转化为多种平台的独立本地应用。…

java 项目使用 acitiviti 流程引擎中的人员设置

学习目标&#xff1a; 目标 [ ]了解 java 项目使用 acitiviti 流程引擎中的人员设置 知识小记&#xff1a; - [x] 1、人员选择说明 - [x] 2、分配任务候选人 任务的候选人是指有权限对该任务进行操作的潜在用户群体&#xff0c;这个用户群体有权限处理(处理、完成)该任务…

最多可以派出多少支球队

最多可以派出多少支球队 解决“最多可以派出多少支球队”的问题需要准确理解题目要求&#xff0c;选择合适的算法&#xff08;如贪心算法和双指针技术&#xff09;&#xff0c;并注意对原始数据进行适当的预处理&#xff08;如排序&#xff09;。在编程实现过程中&#xff0c;有…

MySQL索引重要知识点

1.什么是索引&#xff1f; 索引在项目中是比较常见的&#xff0c;它是帮助MySQL高效获取数据的数据结构&#xff0c;主要是用来提高数据检索的效率&#xff0c;降低数据库的I0成本&#xff0c;同时通过索引列对数据进行排序&#xff0c;降低数据排序的成本&#xff0c;也能降低…