• 标准库标头 <bit>(C++20)学习


    头文件是数值库的一部分。定义用于访问、操作和处理各个位和位序列的函数。例如,有函数可以旋转位、查找连续集或已清除位的数量、查看某个数是否为 2 的整数幂、查找表示数字的最小位数等。

    类型

    endian

    (C++20)

    指示标量类型的端序
    (枚举)

    函数

    bit_cast

    (C++20)

    将一个类型的对象表示重解释为另一类型的对象表示
    (函数模板)

    byteswap

    (C++23)

    反转给定整数值中的字节
    (函数模板)

    has_single_bit

    (C++20)

    检查一个数是否为 2 的整数次幂
    (函数模板)

    bit_ceil

    (C++20)

    寻找不小于给定值的最小的二的整数次幂
    (函数模板)

    bit_floor

    (C++20)

    寻找不大于给定值的最大的二的整数次幂
    (函数模板)

    bit_width

    (C++20)

    寻找表示给定值所需的最小位数
    (函数模板)

    rotl

    (C++20)

    计算逐位左旋转的结果
    (函数模板)

    rotr

    (C++20)

    计算逐位右旋转的结果
    (函数模板)

    countl_zero

    (C++20)

    从最高位起计量连续的 0 位的数量
    (函数模板)

    countl_one

    (C++20)

    从最高位起计量连续的 1 位的数量
    (函数模板)

    countr_zero

    (C++20)

    从最低位起计量连续的 0 位的数量
    (函数模板)

    countr_one

    (C++20)

    从最低位起计量连续的 1 位的数量
    (函数模板)

    popcount

    (C++20)

    计量无符号整数中为 1 的位的数量
    (函数模板)

    下面来看一下它的具体使用示例:

    endian判断CPU的大小端序

    1. #include
    2. #include
    3. //检测处理器端序,返回值:0表大端序,1表示小端序
    4. //小端序低位存放低地址,例如:16bit的数0x1234在小端序模式CPU内存中的存放方式(假设从地址0x2000开始存放)为
    5. //0x2000 0x34
    6. //0x2001 0x12
    7. int checkCPUendian()
    8. {
    9. union w
    10. {
    11. int a;
    12. char b;
    13. }c;
    14. c.a = 1;
    15. return (c.b == 1);
    16. }
    17. int main()
    18. {
    19. if constexpr (std::endian::native == std::endian::big)
    20. std::cout << "大端\n";
    21. else if constexpr (std::endian::native == std::endian::little)
    22. std::cout << "小端\n";
    23. else
    24. std::cout << "混合端序\n";
    25. int ret = checkCPUendian();
    26. std::cout << "ret======" << ret << std::endl;
    27. if (ret)
    28. std::cout << "CPU为小端序\n";
    29. else
    30. std::cout << "CPU为大端序\n";
    31. return 0;
    32. }

    运行结果:

    运行的时候要把编译器设置为C++20或最新的c++标准

     函数示例:

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. template
    9. void dump(T v, char term = '\n')
    10. {
    11. std::cout << std::hex << std::uppercase << std::setfill('0')
    12. << std::setw(sizeof(T) * 2) << v << " : ";
    13. for (std::size_t i{}; i != sizeof(T); ++i, v >>= 8)
    14. std::cout << std::setw(2) << static_cast<unsigned>(T(0xFF) & v) << ' ';
    15. std::cout << std::dec << term;
    16. }
    17. static_assert(std::popcount(0xFULL) == 4);
    18. int main()
    19. {
    20. //1.bit_cast example 将一个类型的对象表示重解释为另一类型的对象表示
    21. float f = std::numeric_limits<float>::infinity();
    22. int i = std::bit_cast<int>(f);
    23. std::cout << "float f = " << std::hex << f
    24. << "\nstd::bit_cast(f) = " << std::hex << i << '\n';
    25. //2.byteswap example反转给定整数值中的字节
    26. static_assert(std::byteswap('a') == 'a');
    27. std::cout << "U16 的 byteswap:\n";
    28. constexpr auto x = std::uint16_t(0xCAFE);
    29. dump(x);
    30. dump(std::byteswap(x));
    31. std::cout << "\nU32 的 byteswap:\n";
    32. constexpr auto y = std::uint32_t(0xDEADBEEFu);
    33. dump(y);
    34. dump(std::byteswap(y));
    35. std::cout << "\nU64 的 byteswap:\n";
    36. constexpr auto z = std::uint64_t{ 0x0123456789ABCDEFull };
    37. dump(z);
    38. dump(std::byteswap(z));
    39. //3.has_single_bit example检查一个数是否为 2 的整数次幂
    40. for (auto u = 0u; u != 10; ++u)
    41. {
    42. std::cout << "u = " << u << " = " << std::bitset<4>(u);
    43. if (std::has_single_bit(u)) // P1956R1 前为 `ispow2`
    44. std::cout << " = 2^" << std::log2(u) << " (为二的幂)";
    45. std::cout << '\n';
    46. }
    47. //4.bit_ceil example寻找不小于给定值的最小的二的整数次幂
    48. using bin = std::bitset<8>;
    49. for (unsigned x{ 0 }; x != 10; ++x)
    50. {
    51. unsigned const z = std::bit_ceil(x); // P1956R1 前为 `ceil2`
    52. std::cout << "bit_ceil( " << bin(x) << " ) = " << bin(z) << '\n';
    53. }
    54. //5.bit_floor example寻找不大于给定值的最大的二的整数次幂
    55. using bin = std::bitset<8>;
    56. for (unsigned x = 0; x != 10; ++x)
    57. {
    58. auto const z = std::bit_floor(x); // P1956R1 前为 `floor2`
    59. std::cout << "bit_floor( " << bin(x) << " ) = " << bin(z) << '\n';
    60. }
    61. //6.bit_width example寻找表示给定值所需的最小位数
    62. for (unsigned x{ 0 }; x != 8; ++x)
    63. {
    64. std::cout << "bit_width( "
    65. << std::bitset<4>{x} << " ) = "
    66. << std::bit_width(x) << '\n';
    67. }
    68. //7.rotl example计算逐位左旋转的结果
    69. std::uint8_t i7 = 0b00011101;
    70. std::cout << "i7 = " << std::bitset<8>(i7) << '\n';
    71. std::cout << "rotl(i7,0) = " << std::bitset<8>(std::rotl(i7, 0)) << '\n';
    72. std::cout << "rotl(i7,1) = " << std::bitset<8>(std::rotl(i7, 1)) << '\n';
    73. std::cout << "rotl(i7,4) = " << std::bitset<8>(std::rotl(i7, 4)) << '\n';
    74. std::cout << "rotl(i7,9) = " << std::bitset<8>(std::rotl(i7, 9)) << '\n';
    75. std::cout << "rotl(i7,-1) = " << std::bitset<8>(std::rotl(i7, -1)) << '\n';
    76. //8.rotr example计算逐位右旋转的结果
    77. std::uint8_t i8 = 0b00011101;
    78. std::cout << "i8 = " << std::bitset<8>(i8) << '\n';
    79. std::cout << "rotr(i8,0) = " << std::bitset<8>(std::rotr(i8, 0)) << '\n';
    80. std::cout << "rotr(i8,1) = " << std::bitset<8>(std::rotr(i8, 1)) << '\n';
    81. std::cout << "rotr(i8,9) = " << std::bitset<8>(std::rotr(i8, 9)) << '\n';
    82. std::cout << "rotr(i8,-1) = " << std::bitset<8>(std::rotr(i8, -1)) << '\n';
    83. //9.countl_zero example从最高位起计量连续的 0 位的数量
    84. for (const std::uint8_t i : {0, 0b11111111, 0b11110000, 0b00011110})
    85. std::cout << "countl_zero( " << std::bitset<8>(i) << " ) = "
    86. << std::countl_zero(i) << '\n';
    87. //10.countl_one example从最高位起计量连续的 1 位的数量
    88. for (const std::uint8_t i : {0, 0b11111111, 0b01111111, 0b11100011})
    89. std::cout << "countl_one( " << std::bitset<8>(i) << " ) = "
    90. << std::countl_one(i) << '\n';
    91. //11.countr_zero example从最低位起计量连续的 0 位的数量
    92. for (const std::uint8_t i : {0, 0b11111111, 0b00011100, 0b00011101})
    93. std::cout << "countr_zero( " << std::bitset<8>(i) << " ) = "
    94. << std::countr_zero(i) << '\n';
    95. //12.countr_one example从最低位起计量连续的 1 位的数量
    96. for (const std::uint8_t i : {0, 0b11111111, 0b11111110, 0b11100011})
    97. std::cout << "countr_one( " << std::bitset<8>(i) << " ) = "
    98. << std::countr_one(i) << '\n';
    99. //13.popcount example计量无符号整数中为 1 的位的数量
    100. for (const std::uint8_t x : {0, 0b00011101, 0b11111111})
    101. std::cout << "popcount( " << std::bitset<8>(x) << " ) = "
    102. << std::popcount(x) << '\n';
    103. return 0;
    104. }

    运行结果:

    参考

    https://learn.microsoft.com/zh-cn/cpp/standard-library/bit-functions?view=msvc-170#bit_cast
    https://zh.cppreference.com/w/cpp/header/bit

  • 相关阅读:
    kube-prometheus 系列1 项目介绍
    一文看懂MySQL的行锁
    猿创征文|〖Python 数据库开发实战 - Python与MySQL交互篇⑯〗- 项目实战 - 实现用户管理 - 新增用户功能
    centos7安装yum的暴力直接办法
    java毕业设计——基于java+mysql+socket的即时通讯软件设计与实现(毕业论文+程序源码)——即时通讯软件
    4. 【自动驾驶与机器人中的SLAM技术】点云中的拟合问题和K近邻
    GEE开发之Landsat_SR计算地表温度(不推荐)
    Jupyter中使用parse报错[args = pp.parse_args()]
    Java实现一个Redis可视化工具
    HC32L110(五) Ubuntu20.04 VSCode的Debug环境配置
  • 原文地址:https://blog.csdn.net/chenyijun/article/details/140108947