探索C/C++ 进制转换之美:从原理到应用(一)

简介: 探索C/C++ 进制转换之美:从原理到应用

一、简介 (Introduction)

进制 前缀表示 整数常量示例 转换库接口 参数及返回值示例
二进制 0b 或 0B 0b1010 std::bitset<> std::bitset<8> binary(42); std::bitset<8> binary(“101010”);
八进制 0 075 std::oct std::cout << std::oct << 42; int oct_num = std::stoi(“52”, nullptr, 8);
十进制 无前缀 42 std::dec std::cout << std::dec << 42; int dec_num = std::stoi(“42”, nullptr, 10);
十六进制 0x 或 0X 0x2A std::hex std::cout << std::hex << 42; int hex_num = std::stoi(“2A”, nullptr, 16);

1.1 C/C++ 进制转换的基本概念 (Basic Concepts of Base Conversion in C/C++)

在计算机科学中,进制转换是一种非常重要的概念。它涉及将一个数值从一个进制系统(比如二进制、八进制、十进制或十六进制)转换到另一个进制系统。在C/C++编程语言中,我们通常会遇到需要对数值进行进制转换的情况,以满足不同的计算需求或实现特定功能。C/C++ 提供了多种进制转换方法,使得程序员能够方便地在不同进制系统之间进行转换。

在C/C++编程语言中,整数常量可以根据其前缀以不同的进制进行表示:

  • 无前缀整数常量表示十进制数(例如:42)
  • 0b0B为前缀的整数常量表示二进制数(例如:0b1010)
  • 0为前缀的整数常量表示八进制数(例如:075)
  • 0x0X为前缀的整数常量表示十六进制数(例如:0x2A)

此外,在C++中,还可以使用std::bitset类、std::stoi函数和std::stoi函数等库功能实现进制转换。

在以下章节中,我们将依次介绍C/C++进行进制转换的底层原理、基本方法和高级应用。希望能够帮助读者更深入地理解C/C++进制转换的原理和技巧,为实际编程工作提供参考。

1.2 进制转换的重要性及应用场景 (Importance and Application Scenarios of Base Conversion)

进制转换在计算机科学和C/C++编程中具有重要的地位,因为它广泛应用于各种实际场景,包括数据存储、通信、加密和解密等。具体的应用场景如下:

  1. 数据存储和压缩: 为了压缩数据和节省存储空间,开发人员需要使用不同的进制表示法(例如二进制或八进制)存储、传输和处理数据。进制转换可帮助开发人员在各种进制之间进行数据转换,以满足不同场景的需求。
  2. 通信协议: 很多通信协议要求以特定进制格式(如十六进制)表示数据。在这些情况下,进制转换变得至关重要,因为它可以帮助开发人员将数据转换为协议规定的格式,从而实现正确的数据传输。
  3. 硬件接口: 当与硬件设备(如传感器、通信设备等)进行编程时,开发人员经常需要处理二进制数据。因此,了解如何在C/C++中完成进制转换对于实现有效的硬件交互至关重要。
  4. 密码学: 在密码学领域,数据加密和解密需要进行多种复杂数学运算和逻辑操作。这些过程中经常涉及到不同的进制系统,如二进制、八进制和十六进制等。掌握C/C++中的进制转换技术可以帮助密码学家在加密算法实现中处理各种进制数据。
  5. 调试与分析: 在进行调试或分析程序时,我们可能需要查看内存中的原始数据。这些数据通常以十六进制表示,因此掌握进制转换技巧可以帮助我们更好地解释这些数据,从而找出潜在问题并优化代码。

这些都是为什么熟练掌握C/C++进制转换技巧极为重要的原因。在后续章节中,我们将详细介绍底层原理、基本方法以及高级应用,助您深入了解和掌握C/C++进制转换的相关知识。

1.3 本文结构与内容安排 (Structure and Content Arrangement of the Article)

为了帮助读者全面了解C/C++进制转换的相关知识,本文将从以下几个方面进行深入介绍:

  1. C/C++ 进制转换的底层原理:本部分将对计算机中的各种进制(二进制、八进制、十进制和十六进制)进行简要介绍,解析C/C++进行进制转换的基本原理以及类型转换与进制转换之间的关系。
  2. C/C++ 基本进制转换方法:在这一部分,我们将介绍C/C++进行八进制、十进制、十六进制之间的转换,以及二进制与其他进制之间的转换的基本方法。此外,还将探讨有关符号数进制转换的相关技巧。
  3. C/C++ 高级进制转换应用:本部分将向读者介绍在C/C++中不同进制表示法的读写,如何使用位操作符进行进制转换以及使用C++标准库中的进制转换功能。
  4. 总结与展望:在文章的最后一部分,将对前面所介绍的方法进行总结,并对未来发展与展望进行简要阐述。

通过对以上内容的深入讨论,我们希望能够帮助读者全面掌握C/C++的进制转换知识,为实际应用提供有力支持。在阅读本文的过程中,建议读者动手实践每个章节的示例代码,以更好地理解和掌握C/C++进制转换的技巧。

二、C/C++ 进制转换的底层原理 (Low-level Principles of Base Conversion in C/C++)

2.1 二进制、八进制、十进制与十六进制 (Binary, Octal, Decimal and Hexadecimal)

在计算机科学中,进制指的是数字系统的基数,也就是计算一个数值所用的基本单位数量。下面简要介绍四种常用的进制系统:

  1. 二进制 (Binary):二进制系统使用0和1两个数字表示数值。每一位只有两种可能的取值(0 或 1),向左移动一位相当于乘以 2。计算机底层使用二进制来存储和处理信息,因为它易于用电子电路实现。
  2. 八进制 (Octal):八进制系统使用数字0至7表示数值。每一位有8种可能的取值(0, 1, …, 7),向左移动一位相当于乘以 8。八进制在计算机科学中的应用主要是为了方便地表示二进制数,因为每三位二进制数可以转换为一位八进制数。
  3. 十进制 (Decimal):十进制系统使用数字0至9表示数值。每一位有10种可能的取值(0, 1, …, 9),向左移动一位相当于乘以 10。我们在日常生活中广泛使用十进制数,在不涉及底层计算机实现细节的编程任务中,通常会用十进制进行数值表示和运算。
  4. 十六进制 (Hexadecimal):十六进制系统使用数字0至9和字母A至F表示数值(其中A至F分别代表10-15)。每一位有16种可能的取值(0, 1, …, 9, A, B, C, D, E, F),向左移动一位相当于乘以 16。与八进制类似,使用十六进制主要是为了简化二进制数表示,每四位二进制数可以转换为一位十六进制数。

了解这些进制系统对于理解C/C++中的进制转换至关重要,接下来我们将讨论C/C++进制转换的基本原理。

2.2 C/C++ 进制转换的基本原理 (Basic Principles of Base Conversion in C/C++)

在C/C++编程中,使用进制转换技巧主要是为了在不同进制之间表示和处理数据。以下简要介绍C/C++进制转换的基本原理:

  1. 整数存储原理:计算机内部使用二进制系统存储整数。实际上,无论整数以二进制、八进制、十进制,还是十六进制表示,计算机内存中的存储形式都是相同的。当我们在C/C++中进行进制转换时,实际上是在操作这些二进制表示的数据。
  2. 数字进制与字符串表示的关系:在C/C++中,进制转换通常涉及将整数值在不同进制的字符串形式之间进行转换。例如,将整数42的十进制形式(“42”)转换为二进制形式(“101010”)。实际上,这种转换并不改变数值本身,而只是改变了它的表示形式。
  3. 进制转换算法:在C/C++中实现进制转换的关键是理解并掌握相应的转换算法。对于不同进制之间的转换,可以使用除法、取余运算和加法等基本数学运算实现。例如,将二进制数转换为十进制数时,可以通过将每一位乘以对应位权(2的指数幂)再求和实现。

通过理解C/C++进制转换的基本原理,我们可以更好地掌握在编程中如何在不同进制之间表示和处理数据。接下来,我们将探讨类型转换与进制转换之间的关系。

2.3 类型转换与进制转换 (Type Conversion and Base Conversion)

类型转换和进制转换是C/C++编程中两个密切相关的概念,它们在实际编程应用中起到了关键作用。下面简要介绍它们之间的关系:

  1. 类型转换:类型转换是指在C/C++编程中将一个数据类型的值转换为另一个数据类型的值。例如,将一个int类型的值转换为float类型的值。类型转换可以分为隐式类型转换和显式类型转换。隐式类型转换是编译器自动进行的转换,例如将一个较小的整数类型值赋给一个较大的整数类型变量。显式类型转换是程序员通过类型转换运算符(如static_cast)手动进行的转换。
  2. 与进制转换的关系:类型转换与进制转换在实践中经常一起使用。在进制转换过程中,我们通常需要首先将一个数值在不同数据类型之间进行转换,然后再将其转换为另一种进制。例如,在将一个二进制字符串转换为整数时,我们会先将字符串类型的二进制表示转换为整数值,然后再将二进制数转换为十进制数。在C/C++中,这类转换操作通常使用标准库函数实现,如std::stoistd::stol等。
  3. 注意事项:使用类型转换和进制转换时需要注意以下几点:
  • 遵循类型转换规则和进制转换算法,避免出现意外的结果。
  • 在进行进制转换时,务必考虑数值的范围,以防止溢出。
  • 在编写代码时,优先使用显式类型转换以明确表达转换意图,提高代码可读性。
  • 在实际应用中,根据需求选择合适的数据类型以及进制表示法,以提高运行效率和内存使用效率。

通过深入理解类型转换与进制转换之间的关系,我们可以更好地掌握C/C++编程中涉及进制转换的问题,并为实际应用提供有效解决方案。

三、C/C++ 基本进制转换方法 (Basic Base Conversion Methods in C/C++)

3.1 八进制、十进制、十六进制之间的转换 (Conversion between Octal, Decimal and Hexadecimal)

3.1.1 八进制与十六进制互转 (Octal and Hexadecimal Conversion)

在C/C++编程中,要将八进制数与十六进制数进行互相转换,通常需要经过以下几个步骤:

  1. 先将八进制数转换为十进制数。
  2. 再将十进制数转换为十六进制数。

以下是具体的转换示例:

  • 八进制转十六进制
#include <iostream>
#include <cstdio>
#include <sstream>
int main() {
    std::string octal_str = "75";
    int decimal_num;
    // 将八进制字符串转换为十进制整数
    std::istringstream(octal_str) >> std::oct >> decimal_num;
    // 将十进制整数转换为十六进制字符串
    std::stringstream hex_ss;
    hex_ss << std::hex << decimal_num;
    std::string hexadecimal_str = hex_ss.str();
    std::cout << "Hexadecimal: " << hexadecimal_str << std::endl;
    return 0;
}
  • 十六进制转八进制
#include <iostream>
#include <cstdio>
#include <sstream>
int main() {
    std::string hex_str = "2A";
    int decimal_num;
    // 将十六进制字符串转换为十进制整数
    std::istringstream(hex_str) >> std::hex >> decimal_num;
    // 将十进制整数转换为八进制字符串
    std::stringstream octal_ss;
    octal_ss << std::oct << decimal_num;
    std::string octal_str = octal_ss.str();
    std::cout << "Octal: " << octal_str << std::endl;
    return 0;
}

通过上述示例,我们可以学会在C/C++中实现八进制与十六进制的互相转换。接下来,我们将介绍如何在八进制与十进制之间进行转换。

3.1.2 八进制与十进制互转 (Octal and Decimal Conversion)

在C/C++编程中,要实现八进制与十进制之间的转换,我们可以使用标准库函数和流操作进行转换。

以下是具体的转换示例:

  • 八进制转十进制:
#include <iostream>
#include <sstream>
int main() {
    std::string octal_str = "75";
    int decimal_num;
    // 将八进制字符串转换为十进制整数
    std::istringstream(octal_str) >> std::oct >> decimal_num;
    std::cout << "Decimal: " << decimal_num << std::endl;
    return 0;
}
  • 十进制转八进制:
#include <iostream>
#include <sstream>
int main() {
    int decimal_num = 61;
    std::stringstream octal_ss;
    // 将十进制整数转换为八进制字符串
    octal_ss << std::oct << decimal_num;
    std::string octal_str = octal_ss.str();
    std::cout << "Octal: " << octal_str << std::endl;
    return 0;
}

通过上述示例,我们可以学会如何在C/C++中实现八进制与十进制之间的转换。下一节,我们将介绍如何在十进制与十六进制之间进行转换。

3.2 二进制与其他进制之间的转换 (Conversion between Binary and Other Bases)

3.2.1 二进制与八进制互转 (Binary and Octal Conversion)

在C/C++编程中,要实现二进制与八进制之间的转换,我们可以使用一些标准库函数和流操作进行转换。

以下是具体的转换示例:

  • 二进制转八进制:
#include <iostream>
#include <bitset>
#include <sstream>
int main() {
    std::string binary_str = "101010";
    std::bitset<32> binary_bitset(binary_str);
    std::stringstream octal_ss;
    // 将二进制字符串转换为对应的十进制整数
    unsigned long decimal_num = binary_bitset.to_ulong();
    // 将十进制整数转换为八进制字符串
    octal_ss << std::oct << decimal_num;
    std::string octal_str = octal_ss.str();
    std::cout << "Octal: " << octal_str << std::endl;
    return 0;
}
  • 八进制转二进制:
#include <iostream>
#include <bitset>
#include <sstream>
int main() {
    std::string octal_str = "52";
    int decimal_num;
    // 将八进制字符串转换为十进制整数
    std::istringstream(octal_str) >> std::oct >> decimal_num;
    // 将十进制整数转换为二进制字符串
    std::bitset<32> binary_bitset(decimal_num);
    std::string binary_str = binary_bitset.to_string();
    // 去除字符串前导零
    size_t non_zero_pos = binary_str.find_first_not_of('0');
    binary_str = binary_str.substr(non_zero_pos);
    std::cout << "Binary: " << binary_str << std::endl;
    return 0;
}

通过上述示例,我们可以学会如何在C/C++中实现二进制与八进制之间的转换。接下来,我们将介绍如何在二进制与十进制之间进行转换。

3.2.2 二进制与十进制互转 (Binary and Decimal Conversion)

在C/C++编程中,要实现二进制与十进制之间的转换,我们可以使用一些标准库函数和流操作进行转换。

以下是具体的转换示例:

  • 二进制转十进制:
#include <iostream>
#include <bitset>
int main() {
    std::string binary_str = "101010";
    std::bitset<32> binary_bitset(binary_str);
    // 将二进制字符串转换为对应的十进制整数
    unsigned long decimal_num = binary_bitset.to_ulong();
    std::cout << "Decimal: " << decimal_num << std::endl;
    return 0;
}
  • 十进制转二进制:
#include <iostream>
#include <bitset>
int main() {
    int decimal_num = 42;
    // 将十进制整数转换为二进制字符串
    std::bitset<32> binary_bitset(decimal_num);
    std::string binary_str = binary_bitset.to_string();
    // 去除字符串前导零
    size_t non_zero_pos = binary_str.find_first_not_of('0');
    binary_str = binary_str.substr(non_zero_pos);
    std::cout << "Binary: " << binary_str << std::endl;
    return 0;
}

通过上述示例,我们可以学会如何在C/C++中实现二进制与十进制之间的转换。接下来,我们将介绍如何在二进制与十六进制之间进行转换。

3.2.3 二进制与十六进制互转 (Binary and Hexadecimal Conversion)

在C/C++编程中,要实现二进制与十六进制之间的转换,我们可以使用一些标准库函数和流操作进行转换。

以下是具体的转换示例:

  • 二进制转十六进制:
#include <iostream>
#include <bitset>
#include <sstream>
int main() {
    std::string binary_str = "101010";
    std::bitset<32> binary_bitset(binary_str);
    std::stringstream hex_ss;
    // 将二进制字符串转换为对应的十进制整数
    unsigned long decimal_num = binary_bitset.to_ulong();
    // 将十进制整数转换为十六进制字符串
    hex_ss << std::hex << decimal_num;
    std::string hex_str = hex_ss.str();
    std::cout << "Hexadecimal: " << hex_str << std::endl;
    return 0;
}
  • 十六进制转二进制:
#include <iostream>
#include <bitset>
#include <sstream>
int main() {
    std::string hex_str = "2A";
    int decimal_num;
    // 将十六进制字符串转换为十进制整数
    std::istringstream(hex_str) >> std::hex >> decimal_num;
    // 将十进制整数转换为二进制字符串
    std::bitset<32> binary_bitset(decimal_num);
    std::string binary_str = binary_bitset.to_string();
    // 去除字符串前导零
    size_t non_zero_pos = binary_str.find_first_not_of('0');
    binary_str = binary_str.substr(non_zero_pos);
    std::cout << "Binary: " << binary_str << std::endl;
    return 0;
}

通过上述示例,我们可以学会如何在C/C++中实现二进制与十六进制之间的转换。接下来,我们将介绍有关符号数进制转换的方法。

3.3 符号数进制转换 (Signed Number Base Conversion)

对于带符号数(signed numbers)的进制转换,我们需要考虑数值的符号以及处理负数时的二进制表示法(通常使用补码表示法)。以下是一些建议和示例以实现带符号数的进制转换。

注意:在负数二进制表示中,最高位(最左边)表示符号位,1表示负数,0表示正数。

  • 使用补码表示法转换正负数:

将一个负数转换为补码表示法,需要执行以下步骤:

  1. 将该负数转换为其绝对值的二进制形式。
  2. 将所得到的二进制数按位取反(将0变为1,将1变为0)。
  3. 在此基础上加1

例:将-5以补码形式表示为8位二进制数

1. 绝对值的二进制表示为:0000 0101
2. 按位取反得到:        1111 1010
3. 加1得到补码:          1111 1011
  • 负数的二进制转十进制:

要将负数的二进制转换为十进制,务必先将这个数从补码形式转换为其真实的十进制表示,然后根据符号位决定是否将十进制值设为负数。

以下是一个使用C++进行带符号数二进制与十进制转换的示例:

#include <iostream>
#include <bitset>
#include <cstdint>
int main() {
    std::string binary_str = "11111011"; // 补码形式表示的 -5
    std::bitset<8> binary_bitset(binary_str);
    // 将二进制字符串转换为对应的(有符号)十进制整数
    int8_t decimal_num = static_cast<int8_t>(binary_bitset.to_ulong());
    std::cout << "Decimal: " << static_cast<int>(decimal_num) << std::endl;
    return 0;
}

这些示例和建议可以帮助您更好地理解和实现带符号数的进制转换。在实际编程中,请根据自己的需求选择合适的方法和函数。在处理有符号数时,请务必注意数值的范围以避免溢出。

3.4 符号数进制转换的数学方法

在将带符号数进行进制转换时,我们需要首先确定符号位。对于负数,需要采用补码表示。在接下来的部分中,我将提供数学方法以实现各种进制之间的转换。

以二进制和十进制间互转为例:

正数
  1. 二进制转十进制:

例如,将二进制数 1101 转换为十进制时,按权展开:

(1 × 2^3) + (1 × 2^2) + (0 × 2^1) + (1 × 2^0) = 8 + 4 + 0 + 1 = 13。

  1. 十进制转二进制:

例如,将十进制数 13 转换为二进制时,执行连续除法:

13 ÷ 2 = 6 ...余 1
 6 ÷ 2 = 3 ...余 0
 3 ÷ 2 = 1 ...余 1
 1 ÷ 2 = 0 ...余 1

由此得到二进制数 1101。

负数

对于负数,首先将其绝对值转换为二进制,然后转换为补码表示。

例如,将 -13 转换为二进制:

  1. 将绝对值 13 转换为二进制:1101
  2. 按位取反(1 变为 0,0 变为 1):0010
  3. 加 1:0011,补码表示为 1111。

下面是将补码表示的负数从二进制转换为十进制的方法:

例如,将补码形式表示的二进制数 1111 转换为十进制数:

  1. 减 1:1110
  2. 按位取反:0001
  3. 按权展开:(0 × 2^3) + (0 × 2^2) + (0 × 2^1) + (1 × 2^0) = 1
  4. 添加负号,得到 -1。

对于八进制和十六进制与其他进制的转换,可以先将数值转换为二进制,然后再转换为目标进制。


探索C/C++ 进制转换之美:从原理到应用(二)https://developer.aliyun.com/article/1464272

目录
相关文章
|
4月前
|
C++
【C++】深入解析C/C++内存管理:new与delete的使用及原理(二)
【C++】深入解析C/C++内存管理:new与delete的使用及原理
|
4月前
|
编译器 C++ 开发者
【C++】深入解析C/C++内存管理:new与delete的使用及原理(三)
【C++】深入解析C/C++内存管理:new与delete的使用及原理
111 3
|
4月前
|
存储 C语言 C++
【C++】深入解析C/C++内存管理:new与delete的使用及原理(一)
【C++】深入解析C/C++内存管理:new与delete的使用及原理
119 2
|
1月前
|
编译器 数据安全/隐私保护 C++
【C++面向对象——继承与派生】派生类的应用(头歌实践教学平台习题)【合集】
本实验旨在学习类的继承关系、不同继承方式下的访问控制及利用虚基类解决二义性问题。主要内容包括: 1. **类的继承关系基础概念**:介绍继承的定义及声明派生类的语法。 2. **不同继承方式下对基类成员的访问控制**:详细说明`public`、`private`和`protected`继承方式对基类成员的访问权限影响。 3. **利用虚基类解决二义性问题**:解释多继承中可能出现的二义性及其解决方案——虚基类。 实验任务要求从`people`类派生出`student`、`teacher`、`graduate`和`TA`类,添加特定属性并测试这些类的功能。最终通过创建教师和助教实例,验证代码
50 5
|
4月前
|
存储 并行计算 安全
C++多线程应用
【10月更文挑战第29天】C++ 中的多线程应用广泛,常见场景包括并行计算、网络编程中的并发服务器和图形用户界面(GUI)应用。通过多线程可以显著提升计算速度和响应能力。示例代码展示了如何使用 `pthread` 库创建和管理线程。注意事项包括数据同步与互斥、线程间通信和线程安全的类设计,以确保程序的正确性和稳定性。
|
4月前
|
C++
C++番外篇——虚拟继承解决数据冗余和二义性的原理
C++番外篇——虚拟继承解决数据冗余和二义性的原理
64 1
|
4月前
|
存储 编译器 C++
【C++篇】揭开 C++ STL list 容器的神秘面纱:从底层设计到高效应用的全景解析(附源码)
【C++篇】揭开 C++ STL list 容器的神秘面纱:从底层设计到高效应用的全景解析(附源码)
103 2
|
5月前
|
编译器 C++
【C++核心】函数的应用和提高详解
这篇文章详细讲解了C++函数的定义、调用、值传递、常见样式、声明、分文件编写以及函数提高的内容,包括函数默认参数、占位参数、重载等高级用法。
45 3
|
2天前
|
编译器 C语言 C++
类和对象的简述(c++篇)
类和对象的简述(c++篇)
|
1月前
|
C++ 芯片
【C++面向对象——类与对象】Computer类(头歌实践教学平台习题)【合集】
声明一个简单的Computer类,含有数据成员芯片(cpu)、内存(ram)、光驱(cdrom)等等,以及两个公有成员函数run、stop。只能在类的内部访问。这是一种数据隐藏的机制,用于保护类的数据不被外部随意修改。根据提示,在右侧编辑器补充代码,平台会对你编写的代码进行测试。成员可以在派生类(继承该类的子类)中访问。成员,在类的外部不能直接访问。可以在类的外部直接访问。为了完成本关任务,你需要掌握。
68 19