RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1473279
Accepted
Stanislav Volodarskiy
Stanislav Volodarskiy
Asked:2022-12-02 15:56:09 +0000 UTC2022-12-02 15:56:09 +0000 UTC 2022-12-02 15:56:09 +0000 UTC

如何以可移植的方式设置像 0x55555555 这样的掩码?

  • 772

一些位操作任务需要所有偶数位的掩码。每次这样的掩码都由一个 0x55555555 形式的常量给出,如果它unsigned需要 32 位就很好。如果是 16 或 64?

如何以适用于类型中任意数量位的方式为所有偶数位定义掩码?该定义必须是编译时常量。

c++
  • 6 6 个回答
  • 169 Views

6 个回答

  • Voted
  1. Best Answer
    HolyBlackCat
    2022-12-02T20:08:29Z2022-12-02T20:08:29Z

    它可以很简单(unsigned int)-1 / 3。

    • 11
  2. Harry
    2022-12-02T18:59:26Z2022-12-02T18:59:26Z

    让我们使用现实生活中的东西

    1. 字节大小为 8 位。
    2. 以字节为单位的整数类型的大小是 2 的幂。

    如果没有,您可以使用 gbg 的答案 :)

    template<unsigned_integral T>
    consteval T mask2()
    {
        T mask = 0x55;
        for(unsigned int i = 1; i < sizeof(T); i*=2)
            mask |= mask << i*8;
        return mask;
    }
    

    仍然是 O(log N):),其中 N 是类型的大小。

    在编译时像 gbg 一样计算 - https://gcc.godbolt.org/z/78EaTqzKK

    • 5
  3. gbg
    2022-12-02T16:41:18Z2022-12-02T16:41:18Z

    使用constexpr-功能:

    #include <iostream>
    #include <iomanip>
    using namespace std;
    
    template <typename T> 
    T constexpr mask101() 
    {
        T ret = 0;
        for(T mask=1;mask;mask<<=2)
        {
            ret|=mask;
        }
        return ret;
    }
    
    int main() 
    {
        constexpr auto test = mask101<size_t>();
        cout << std::hex <<"0x" << test << endl;
        cout << std::hex <<"0x" << mask101<int32_t>() << endl;
        cout << std::hex <<"0x" << mask101<uint16_t>() << endl;
        cout << std::hex <<"0x" << int(mask101<int8_t>()) << endl;
        return 0;
    }
    

    结论:

    0x5555555555555555
    0x55555555
    0x5555
    0x55
    

    ideone 上的代码

    • 3
  4. Stanislav Volodarskiy
    2022-12-02T23:52:13Z2022-12-02T23:52:13Z

    掩码可以表示为总和4 0 + 4 1 + ... + 4 k。根据几何级数和的公式,这个和等于(4 k+1 - 1) / 3。

    如果无符号类型的位数为偶数,则其最大值为2 2k - 1。等于4k - 1。如果将此数字除以三,您将得到所需的掩码。例如,对于unsigned计算UINT_MAX / 3。

    该程序C不会以可移植的方式构建掩码。类型的最大值是作为-1无符号类型的转换获得的。需要再进行一次转换,以便更短的类型的值unsigned同样短。否则,将unsigned使用掩码值unsigned short或获取类型unsigned char:

    #include <stdio.h>
    
    #define MASK(type) ((type)((type)-1 / 3))
    
    int main() {
        printf("0x%hhx\n", MASK(unsigned char     ));
        printf("0x%hx\n" , MASK(unsigned short    ));
        printf("0x%x\n"  , MASK(unsigned          ));
        printf("0x%lx\n" , MASK(unsigned long     ));
        printf("0x%llx\n", MASK(unsigned long long));
    }
    
    $ gcc -std=c11 -pedantic -Wall -Wextra -Werror mask.c && ./a.out 
    0x55
    0x5555
    0x55555555
    0x5555555555555555
    0x5555555555555555
    

    相同的C++:

    #include <iomanip>
    #include <iostream>
    
    template<typename T> constexpr T mask() { return static_cast<T>(-1) / 3; }
    
    int main() {
        std::cout << std::hex;
        std::cout << static_cast<unsigned>(mask<unsigned char     >()) << '\n';
        std::cout <<                       mask<unsigned short    >()  << '\n';
        std::cout <<                       mask<unsigned          >()  << '\n';
        std::cout <<                       mask<unsigned long     >()  << '\n';
        std::cout <<                       mask<unsigned long long>()  << '\n';
    }
    
    $ g++ -std=c++17 -pedantic -Wall -Wextra -Werror mask.cpp && ./a.out 
    55
    5555
    55555555
    5555555555555555
    5555555555555555
    

    但是,如果您的计算机具有奇数位数的类型怎么办?例如,一个五字节的整数,一个字节有九位。必须采取更多步骤:

    #define DRAFT_MASK(type) ((type)((type)-1 / 3))
    #define ODD_BITS(type) ((DRAFT_MASK(type) & 1) ^ 1)
    #define MASK(type) ((type)(DRAFT_MASK(type) << ODD_BITS(type) | 1))
    

    DRAFT_MASK- 一个老式的面具。如果位数是奇数,则

    (2 2k+1 - 1) / 3 = (2 4 k - 1) / 3 = (2(4 k - 1) + 1) / 3 = 2((4 k - 1) / 3) + 1 / 3 .

    左边的项是双重掩码。右项四舍五入为零——整数除法。结果是一个突出显示奇数位的掩码。

    如果类型中的位数为奇数,则构造ODD_BITS(type)等于 1 - 检查掩码的最低有效位。在这种情况下,旧掩码必须向左移动一位并添加最低有效位。这就是它的作用MASK。如果位数为偶数,则结果MASK与 相同DRAFT_MASK。

    当我得到合适的硬件时,我一定会测试它。

    • 3
  5. AlexGlebe
    2022-12-02T19:18:20Z2022-12-02T19:18:20Z

    在 C 中,双重编译有助于创建常量。中的示例gcc:

    gcc makemask.c -o makemask && makemask > mask.h

    我们使用类型大小的模板编写:

    # define MAKECONST( T , N ) { \
      printf ( "%s const %s = 0x" , ( # T ) , ( N ) ) ; \
      for ( int i = 0 ; i < sizeof ( T ) ; ++ i ) \
        printf ( "%x" , 0x55 ) ; \
      puts ( " ;" ) ; \
    }
    
    # include <stdio.h>
    
    int main() {
      MAKECONST ( unsigned short int , "ushort_mask" ) ;
      MAKECONST ( unsigned int , "uint_mask" ) ;
      fflush ( stdout ) ;
    }
    

    我们得到一个标题:mask.h

    unsigned short int const ushort_mask = 0x5555 ;
    unsigned int const uint_mask = 0x55555555 ;
    
    • 2
  6. user7860670
    2022-12-02T19:57:30Z2022-12-02T19:57:30Z

    具有 2 的幂的值,这可以在没有循环的情况下计算:

    template<unsigned long long x_index>
    constexpr auto pow2{2ull * pow2<x_index - 1ull>};
    
    template<>
    constexpr auto pow2<0ull>{1ull};
    
    template<typename x_Integer>
    constexpr x_Integer odd_mask{(pow2<sizeof(x_Integer) * 8ull> - 1ull) / 3ull};
    
    static_assert(0x55u == odd_mask<unsigned char>);
    static_assert(0x5555u == odd_mask<unsigned short>);
    static_assert(0x55555555u == odd_mask<unsigned int>);
    static_assert(0x5555555555555555u == odd_mask<unsigned long long>);
    

    在线编译器

    • 2

相关问题

  • 编译器和模板处理

  • 指针。找到最小数量

  • C++,关于枚举类对象初始化的问题

  • 函数中的二维数组

  • 无法使用默认构造函数创建类对象

  • C++ 和循环依赖

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    我看不懂措辞

    • 1 个回答
  • Marko Smith

    请求的模块“del”不提供名为“default”的导出

    • 3 个回答
  • Marko Smith

    "!+tab" 在 HTML 的 vs 代码中不起作用

    • 5 个回答
  • Marko Smith

    我正在尝试解决“猜词”的问题。Python

    • 2 个回答
  • Marko Smith

    可以使用哪些命令将当前指针移动到指定的提交而不更改工作目录中的文件?

    • 1 个回答
  • Marko Smith

    Python解析野莓

    • 1 个回答
  • Marko Smith

    问题:“警告:检查最新版本的 pip 时出错。”

    • 2 个回答
  • Marko Smith

    帮助编写一个用值填充变量的循环。解决这个问题

    • 2 个回答
  • Marko Smith

    尽管依赖数组为空,但在渲染上调用了 2 次 useEffect

    • 2 个回答
  • Marko Smith

    数据不通过 Telegram.WebApp.sendData 发送

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5