C++ 中的位移运算符
在 C++ 中,位移运算符按照其名称的含义进行操作,即位移位。根据程序的要求,移位运算符将二进制位向左或向右移动。
整数值应用于这些运算符(int、long、可能是 short 和 byte 或 char)。在某些语言中,对小于 int 的任何数据类型使用移位运算符会自动将操作数的大小调整为 int。
本文将详细讨论 C++ 中的左移和右移运算符及其实现以及相关示例。
C++ 中的左位移位运算符
左移运算符将移位表达式中的位向左移动加法表达式中的位数。移位操作腾出的位位置用零填充,从末尾移出的位被丢弃,包括符号位。
左移运算符需要两个数字。这会移动第一个操作数的位,而第二个操作数决定要移位的位数。
你可以说将整数 a
与整数 b
左移,用 (a<<b)
表示,等效于将 a
乘以 2^b
(2 的 b 次方)。左移运算符用 <<
表示。
例如,M<<k
。这里,M
是第一个操作数,k 是第二个操作数。
让我们取 M=33;
这是二进制的 100001 和 k = 2
。如果 M
左移 2,表示为 M=M<<2
,它将变为 M=M(2^2)
。
因此,M=33(2^2)=132
可以写成 10000100。
例子:
#include <iostream>
using namespace std;
int main()
{
unsigned char x = 6, y = 7;
cout <<"x<<1 = "<< (x<<1) << endl;
cout <<"y<<1 = "<< (y<<1) << endl;
return 0;
}
输出:
x<<1 = 12
y<<1 = 14
在上面的代码中,unsigned char x
和 char y
变量表示一个字符数据类型,其中变量使用所有内存的 8 位,并且没有符号位(在有符号的 char 中存在)。
这里,char x
等于 6,即二进制的 00000110,而 char y
等于 7,即二进制的 00000111。
第一个 print 语句声明将 x
的值左移 1 位;结果是 00001100。第二个打印语句将 y
的值左移 1 位;结果是 00001110。
C++ 中的右位移运算符
右移运算符将移位表达式中的位模式移动加法表达式向右提供的位数。对于无符号值,移位操作腾出的位位置是零填充的。
符号位替换有符号数中的空位位置。如果数字为正,则使用值 0;如果数字为负数,则使用值 1。
右移运算符需要两个数字。这会移动第一个操作数的位,而第二个操作数决定要移位的位数。
你可以说将整数 a
与整数 b
右移,表示为 (a>>b)
,相当于将 a
除以 2^b
(2 的 b 次方)。右移运算符表示为:>>
。
例如,M>>k
。这里,M
是第一个操作数,k
是第二个操作数。
让我们取 M=32;
这是二进制的 100000 和 k = 2
。如果 M
右移 2,表示为 M=M>>2
,那么 M
将变为 M=M/(2^2)
。因此,M=32/(2^2)=8
可以写成 1000。
示例程序:
#include <iostream>
int main()
{
unsigned char x = 6, y = 9;
cout <<"a>>1 = "<< (a >> 1)<< endl;
cout <<"b>>1 = "<< (b >> 1) << endl;
return 0;
}
输出:
x>>1 = 3
y>>1 = 4
在上面的代码中,unsigned char x
和 char y
变量表示变量中的字符数据类型,它使用了内存的所有 8 位,并且没有符号位(在有符号的 char 中存在)。
这里,char x
等于 6,即二进制的 00000110,而 char y
等于 9,即二进制的 00001001。
第一个 print 语句声明将 x
的值右移 1 位;结果是 00000011。第二个打印语句声明将 y
的值右移 1 位;结果是 00000100。
C++ 中浮点数据类型的位移
你不能在 C++ 中对浮点数进行位移,因为它会显示错误,但这是为什么呢?这是因为浮点数以特殊格式存储。
浮点数的 32 位分为两类:有效数和指数。移位可能会将位从指数类别转移到有效数字类别,反之亦然。
例子:
#include <stdio.h>
int main( int ar, char *arg[] )
{
float testFl = 2.5;
printf( "testFloat (before): %f\n", testFl );
testFl = testFl << 1;
printf( "testFloat (after): %f\n", testFl );
return 0;
}
输出:
error: invalid operands to binary << (have 'float' and 'int')
右移或左移将折叠所有位。
C++ 中数组的位移
有一个大小为 n 的数组 ar[]
和一个整数 m
。
目标是通过对存在的所有数组元素执行右移操作来使所有数组元素 > m
。如果你不能这样做,请打印 -1。
例子:
Input: ar[] = { 21, 22, 23, 19 }, m = 34
Output: { 26, 26, 27, 25 }
Explanation:
ar[0] = 10101
After 1 right shift, 11010 → 26
ar[1] = 10110
After 3 right shift, 11010 → 26
ar[2] = 10111
After 1 right shift, 11011 → 27
ar[3] = 10011
After 2 right shift, 11001 → 25
代码:
#include <bits/stdc++.h>
using namespace std;
int setBitNumber(int n)
{
int m = log2(n);
return m;
}
bool check(int ar[], int m, int n)
{
for (int i = 0; i < n; i++) {
if (ar[i] <= m)
return false;
}
return true;
}
void modifyArray(int ar[], int m, int n)
{
for (int i = 0; i < n; i++) {
if (ar[i] > m)
continue;
else {
int bits = setBitNumber(ar[i]);
int el = ar[i];
for (int j = 0; j < bits; j++) {
if (el & 1) {
el >>= 1;
el |= (1 << bits);
}
else {
el >>= 1;
}
if (el > m) {
arr[i] = el;
break;
}
}
}
}
if (check(ar, m, n)) {
for (int i = 0; i < n; i++)
cout << ar[i] << " ";
}
else
cout << -1;
}
int main()
{
int ar[] = { 21, 22, 23, 19 };
int n = sizeof(ar) / sizeof(ar[0]);
int m = 24;
modifyArray(ar, m, n);
return 0;
}
输出:
[26, 26, 27, 25]
程序中执行的主要操作是数组的遍历。它对数组 ar[i]
的每个元素进行右移操作。
如果 ar[i] > m
,则检查条件。如果为真,则更新数组 ar[i]
,否则继续。
如果数组 ar[i] ≤ m
的任何元素,则打印-1,否则打印数组 ar[i]
。
C++ 中的位移位和掩码
掩码指定应保留哪些位以及应清除哪些位。
例子:
Mask: 00001111b
Value: 01010101b
当我们对值应用掩码时,我们希望清除前(高)四位,同时保留最后(低)四位。结果,我们检索到了底部的四位。
输出:
Mask: 00001111b
Value: 01010101b
Result: 00000101b
位移运算符经常与掩码操作一起使用,以将位从一个数字中逐一剥离。以下示例说明了如何将 unsigned char 划分为单独的位数组。
unsigned char y = 0xD5;
unsigned char bit[8];
unsigned char mask = 1;
for(int x = 7;x >= 0;x--) {
bits[x] = y & mask;
y = y >> 1;
}
C++ 中负数的位移
不应使用左右移位运算符输入负数。如果任一操作数是负整数,则结果是未定义的行为。
例如,1 >> -1
和 1 << -1
的结果都是未定义的。
#include <iostream>
int main()
{
unsigned char x = -6,
cout <<"a>>1 = "<< (a >> 1)<< endl;
return 0;
}
输出:
error: undefined behavior in C
在 C++ 中使用 Long 进行位移
数据类型 long 用于位移 32 位或 64 位。
例子:
对于 32 位,
unsigned long A = (1L << 37)
对于 64 位,
unsigned long long A = (1ULL << 37);
使用程序实现以下内容:
#include <stdio.h>
int main(void)
{
long long y = 1ULL;
// Left shift 40 times
y <<= 20;
y <<= 20;
printf("y is %lld\n", y);
return 0;
}
输出:
y is 1099511627776
这里,取一个 64 位变量 long long y
,而 1ULL 是一个无符号 long long int
常量(64 位)。变量 y
移动 40 次并打印出来。
结论
在本文中,我们讨论了 C++ 中的位移位运算符。我们详细了解了 C++ 中的左右移位运算符。
相关文章
在 C++ 中通过掷骰子生成随机值
发布时间:2023/04/09 浏览次数:169 分类:C++
-
本文解释了如何使用时间因子方法和模拟 C++ 中的掷骰子的任意数方法生成随机数。了解它是如何工作的以及它包含哪些缺点。提供了一个 C++ 程序来演示伪数生成器。
在 C++ 中使用模板的链表
发布时间:2023/04/09 浏览次数:158 分类:C++
-
本文解释了使用模板在 C++ 中创建链表所涉及的各个步骤。工作程序演示了一个链表,该链表使用模板来避免在创建新变量时声明数据类型的需要。
在 C++ 中添加定时延迟
发布时间:2023/04/09 浏览次数:142 分类:C++
-
本教程将为你提供有关在 C++ 程序中添加定时延迟的简要指南。这可以使用 C++ 库为我们提供的一些函数以多种方式完成。
在 C++ 中创建查找表
发布时间:2023/04/09 浏览次数:155 分类:C++
-
本文重点介绍如何创建查找表及其在不同场景中的用途。提供了三个代码示例以使理解更容易,并附有代码片段以详细了解代码。
如何在 C++ 中把字符串转换为小写
发布时间:2023/04/09 浏览次数:63 分类:C++
-
介绍了如何将 C++ std::string 转换为小写的方法。当我们在考虑 C++ 中的字符串转换方法时,首先要问自己的是我的输入字符串有什么样的编码
如何在 C++ 中确定一个字符串是否是数字
发布时间:2023/04/09 浏览次数:163 分类:C++
-
本文介绍了如何检查给定的 C++ 字符串是否是数字。在我们深入研究之前,需要注意的是,以下方法只与单字节字符串和十进制整数兼容。
如何在 c++ 中查找字符串中的子字符串
发布时间:2023/04/09 浏览次数:65 分类:C++
-
本文介绍了在 C++ 中检查一个字符串是否包含子字符串的多种方法。使用 find 方法在 C++ 中查找字符串中的子字符串
如何在 C++ 中把字符串转换为 Char 数组
发布时间:2023/04/09 浏览次数:107 分类:C++
-
本文介绍了在 C++ 中把字符串转换为 char 数组的多种方法。使用 std::basic_string::c_str 方法将字符串转换为 char 数组