突破编程_C++_C++14新特性(二进制字面量)

1 二进制字面量的概述

1.1 二进制字面量的概念与重要性

(1)概念

二进制字面量是以 “0b” 或 “0B” 开头的整数字面量,后面跟着一系列二进制数字(即 0 和 1)。这种表示法为开发者提供了一种方便的方式来在代码中表示二进制数。例如,变量 b1 被赋值为二进制数 0b00111011,表示的就是十进制的 59。

(2)重要性

二进制字面量的重要性主要体现在以下几个方面:

  • 提高代码可读性:使用二进制字面量可以直观地表示二进制数,无需通过十进制或其他进制进行转换,从而提高了代码的可读性。对于涉及底层操作或硬件编程的代码,这种表示法尤其有用,因为它能更清晰地展示数据的二进制结构。
  • 简化位操作:位操作是计算机编程中常见的操作,包括位与、位或、位异或、位非和位移等。使用二进制字面量可以更方便地进行这些操作,因为二进制数直接反映了数据的位级表示。
  • 优化性能:在某些情况下,使用二进制字面量可能有助于编译器进行更高效的优化。由于二进制数直接反映了数据的底层表示,编译器可以更容易地识别出可以利用的模式和机会,从而生成更高效的代码。
  • 支持现代编程需求:随着计算机技术的不断发展,越来越多的场景需要直接处理二进制数据。C++14 引入二进制字面量正是为了满足这种需求,使得 C++ 语言更加适应现代编程的需求。

1.2 C++14 对二进制字面量的支持

C++14 对二进制字面量的支持是编程语言发展中一个重要的里程碑,它允许程序员在代码中直接使用二进制数,为处理位操作、硬件编程等底层任务提供了极大的便利。以下是对 C++14 中二进制字面量支持的详细讲解:

(1)语法与表示

在 C++14 中,二进制字面量是通过前缀 0b 或 0B 来表示的。这意味着你可以直接在代码中写下一个以 0b 或 0B 开头的数字序列,来代表一个二进制数。例如,0b1010 代表的就是二进制数 1010,它对应的十进制数是 10。

(2)类型推导

C++14 中,二进制字面量的类型推导遵循与十进制字面量相同的规则。如果没有明确指定类型,编译器会根据字面量的大小来推导其类型。例如,如果二进制字面量的值在 int 类型的范围内,那么它的类型就会被推导为 int。如果它的值超过了 int 类型的范围,那么编译器可能会选择更大的类型,如 long long,来确保能够准确表示该值。

(3)示例

#include <iostream>  
#include <bitset> // 用于输出二进制表示  

int main() {
	// 使用二进制字面量给变量赋值  
	int binaryValue = 0b1010; // 等于十进制的 10  
	unsigned long long largeBinaryValue = 0b1101101010101010101010101010; // 一个更大的二进制数  

	// 输出变量的十进制值  
	std::cout << "binaryValue (decimal): " << binaryValue << std::endl;
	std::cout << "largeBinaryValue (decimal): " << largeBinaryValue << std::endl;

	// 使用 std::bitset 输出变量的二进制表示  
	std::cout << "binaryValue (binary): " << std::bitset<8>(binaryValue) << std::endl;
	std::cout << "largeBinaryValue (binary): " << std::bitset<64>(largeBinaryValue) << std::endl;
	
	return 0;
}

上面代码的输出为:

binaryValue (decimal): 10
largeBinaryValue (decimal): 229288618
binaryValue (binary): 00001010
largeBinaryValue (binary): 0000000000000000000000000000000000001101101010101010101010101010

这个示例创建了两个变量 binaryValue 和 largeBinaryValue,并分别用二进制字面量给它们赋值。另外还使用了 std::bitset 来以二进制形式输出这些变量的值,以便可以更清晰地看到它们的位模式。

2 二进制字面量与位操作

2.1 位与操作(AND)

位与操作是一种基本的位级操作,用于比较两个数的每一位,只有当两个数的对应位都是 1 时,结果的该位才为 1。

位与操作在多种场景中都非常有用,特别是处理位掩码和设置/清除特定位时。以下是一些常见的使用场景:

  • 位掩码:位掩码通常用于选择整数中的特定位。通过将整数与掩码进行位与操作,可以保留掩码中设置为1的位,而将其他位清零。这在硬件编程、网络编程和图形处理中非常常见。

  • 权限检查:在操作系统或权限管理系统中,权限通常表示为一系列位。通过位与操作,可以检查用户是否具有某个特定的权限。

  • 设置和清除特定位:位与操作可以用来清除整数中的特定位,通过将整数与一个除了目标位为0其他位都为1的数进行位与操作,可以确保目标位被清零。同样地,也可以结合其他操作来设置特定位。

如下为样例代码:

#include <iostream>  
#include <bitset> // 用于输出二进制表示  

int main() {
	int binaryValue1 = 0b1010;
	int binaryValue2 = 0b1100;

	int result = binaryValue1 & binaryValue2;

	// 输出结果的十进制表示  
	std::cout << "Result (decimal): " << result << std::endl;

	// 输出结果的二进制表示  
	std::cout << "Result (binary): " << std::bitset<4>(result) << std::endl;

	return 0;
}

上面代码的输出为:

Result (decimal): 8
Result (binary): 1000

2.2 位或操作(OR)

位或操作是一种基本的位级操作,它对两个操作数的每一位执行逻辑或运算。如果两个操作数的某一位至少有一个是 1,那么结果的该位就是 1;否则,结果的该位就是 0。

如下为样例代码:

#include <iostream>  
#include <bitset> // 用于输出二进制表示  

int main() {
	int binaryValue1 = 0b1010;
	int binaryValue2 = 0b0101;

	int result = binaryValue1 | binaryValue2;

	// 输出结果的十进制表示  
	std::cout << "Result (decimal): " << result << std::endl;

	// 输出结果的二进制表示  
	std::cout << "Result (binary): " << std::bitset<4>(result) << std::endl;

	return 0;
}

上面代码的输出为:

Result (decimal): 15
Result (binary): 1111

2.3 位异或操作(XOR)

位异或操作是一种基本的位级运算,它对两个操作数的每一位执行异或运算。如果两个操作数的某一位不同,则结果的该位是 1;如果相同,则结果的该位是 0。

位异或操作在编程中有多种应用,例如:

  • 交换两个变量的值:不使用临时变量,你可以通过位异或操作交换两个变量的值。例如,a = a ^ b; b = a ^ b; a = a ^ b;。
  • 查找唯一出现的元素:在一个数组中,除了一个元素出现一次外,其他元素都出现两次,你可以通过将所有元素进行位异或操作来找到那个只出现一次的元素,因为任何数与自己异或的结果都是 0,而异或操作满足交换律和结合律。
  • 加密和校验:位异或操作常用于简单的加密和解密算法,以及数据校验,因为它能够快速地在两个状态之间切换。

如下为样例代码:

#include <iostream>  
#include <bitset> // 用于输出二进制表示  

int main() {
	int binaryValue1 = 0b1010;
	int binaryValue2 = 0b1100;

	int result = binaryValue1 ^ binaryValue2;

	// 输出结果的十进制表示  
	std::cout << "Result (decimal): " << result << std::endl;

	// 输出结果的二进制表示  
	std::cout << "Result (binary): " << std::bitset<4>(result) << std::endl;

	return 0;
}

上面代码的输出为:

Result (decimal): 6
Result (binary): 0110

2.4 位非操作(NOT)

在 C++ 中,位非操作(NOT)通常指的是对单个整数进行按位取反的操作,这不同于逻辑非操作(!),后者用于对布尔值进行取反。位非操作将整数的每一位都取反,即 0 变为 1,1 变为 0。然而,需要注意的是,C++ 并不直接支持像位与、位或和位异或那样的内置位非运算符。因此,我们不能直接对二进制字面量使用位非运算符。

要对一个整数执行位非操作,我们通常需要使用按位取反运算符 ~。但是,这个运算符作用于整个整数,而不是单独的位。因此,即使你使用二进制字面量来初始化一个整数,你仍然需要对整个整数使用 ~ 运算符来执行位非操作。

如下为样例代码:

#include <iostream>  
#include <bitset> // 用于输出二进制表示  

int main() {
	int binaryValue = 0b1010; // 使用二进制字面量初始化整数  
	std::cout << "Original value (decimal): " << binaryValue << std::endl;
	std::cout << "Original value (binary): " << std::bitset<4>(binaryValue) << std::endl;

	int bitwiseNotValue = ~binaryValue; // 对整数执行位非操作  
	std::cout << "Bitwise NOT value (decimal): " << bitwiseNotValue << std::endl;
	std::cout << "Bitwise NOT value (binary): " << std::bitset<4>(bitwiseNotValue) << std::endl;

	return 0;
}

上面代码的输出为:

Original value (decimal): 10
Original value (binary): 1010
Bitwise NOT value (decimal): -11
Bitwise NOT value (binary): 0101

2.5 位移操作(左移、右移)

在 C++ 中,位移操作(包括左移和右移)是位级操作,用于将整数的所有位向左或向右移动指定的位数。左移操作将位向左移动,右侧用零填充;右移操作将位向右移动,对于无符号整数,左侧用零填充;对于有符号整数,左侧填充的内容取决于具体的实现(可能是零或符号位)。

C++14 引入了二进制字面量,这使得我们可以更直观地表示和操作整数的二进制形式。虽然二进制字面量本身并不直接支持位移操作,但我们可以将它们用作位移操作的源操作数。

(1)定义二进制字面量

int binaryValue = 0b1010; // 二进制字面量,等于十进制的10

(2)执行左移操作

左移操作使用<<运算符。它将左边的操作数的所有位向左移动右边操作数指定的位数,右侧用零填充。

int leftShiftedValue = binaryValue << 1; // 左移一位
对于0b1010左移一位,结果将是:

leftShiftedValue: 0b10100 // 等于十进制的20

(3)执行右移操作

右移操作使用>>运算符。它将左边的操作数的所有位向右移动右边操作数指定的位数。对于有符号整数,左侧填充的内容取决于编译器和平台。对于无符号整数,左侧用零填充。

unsigned int unsignedBinaryValue = 0b1010u; // 无符号二进制字面量  
int signedBinaryValue = 0b1010; // 有符号二进制字面量  
  
unsigned int unsignedRightShiftedValue = unsignedBinaryValue >> 1; // 无符号右移一位  
int signedRightShiftedValue = signedBinaryValue >> 1; // 有符号右移一位

对于无符号整数0b1010u右移一位,结果将是:

unsignedRightShiftedValue: 0b0101 // 等于十进制的5

对于有符号整数0b1010右移一位,结果取决于编译器和平台,但通常是:

signedRightShiftedValue: 0b0101 // 在某些平台/编译器上可能等于十进制的5,但符号位可能保持不变

或者,如果编译器执行算术右移(保留符号位):

signedRightShiftedValue: 0b1010 // 等于十进制的-5(取决于具体的表示和平台)

(4)查看和操作结果

可以使用 std::cout 来打印位移操作的结果,或者使用 std::bitset 来查看结果的二进制表示。

#include <iostream>  
#include <bitset> // 用于输出二进制表示  
  
int main() {  
    int binaryValue = 0b1010;  
  
    int leftShiftedValue = binaryValue << 1;  
    unsigned int unsignedRightShiftedValue = (unsigned int)binaryValue >> 1;  
    int signedRightShiftedValue = binaryValue >> 1;  
  
    std::cout << "Original value (decimal): " << binaryValue << std::endl;  
    std::cout << "Left shifted value (decimal): " << leftShiftedValue << std::endl;  
    std::cout << "Unsigned right shifted value (decimal): " << unsignedRightShiftedValue << std::endl;  
    std::cout << "Signed right shifted value (decimal): " << signedRightShiftedValue << std::endl;  
  
    // 输出结果的二进制表示  
    std::cout << "Left shifted value (binary): " << std::bitset<5>(leftShiftedValue) << std::endl;  
    std::cout << "Unsigned right shifted value (binary): " << std::bitset<4>(unsignedRightShiftedValue) << std::endl;  
    std::cout << "Signed right shifted value (binary): " << std::bitset<4>(signedRightShiftedValue) << std::endl;  
  
    return 0;  
}

上面代码的输出为:

Original value (decimal): 10
Left shifted value (decimal): 20
Unsigned right shifted value (decimal): 5
Signed right shifted value (decimal): 5
Left shifted value (binary): 10100
Unsigned right shifted value (binary): 0101
Signed right shifted value (binary): 0101

(5)位移操作的应用

位移操作在编程中有多种应用,例如:

快速乘法/除法:通过左移或右移操作,可以快速地实现乘以或除以 2 的幂次。例如,x << 3 相当于 x * 8,x >> 3 相当于 x / 8(假设 x 是一个无符号整数,并且右移操作是逻辑右移)。

  • 位字段操作:位移操作经常用于在结构体中操作位字段,这些位字段用来存储小于一个字节大小的数据。

  • 性能优化:在某些情况下,位移操作比乘法或除法操作更快,因此,当性能成为关键因素时,程序员可能会选择使用位移操作。

  • 底层硬件编程:在嵌入式系统或底层硬件编程中,位移操作常用于直接操作硬件寄存器或内存地址。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值