首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++位操作在我的系统上编译时没有错误,但godbolt编译器给出警告/错误

C++位操作在我的系统上编译时没有错误,但godbolt编译器给出警告/错误
EN

Stack Overflow用户
提问于 2019-06-23 16:07:22
回答 1查看 103关注 0票数 0

编辑: Godbolt链接,例如here

所以我有这个例子来展示我制作的宏和它们的用例:

代码语言:javascript
复制
#include <bitset>
#include <iostream>

#define bit_mask(size, offset) (~(~0 << size) << offset)
#define bit_masked_set(dst, src, mask, offset) (dst = (dst & ~mask) | (src << offset))
#define bit_masked_get(src, mask, offset) ((src & mask) >> offset)

constexpr unsigned front_mask = bit_mask(16, 16);
constexpr unsigned back_mask = bit_mask(16, 0);

int main() {
    std::cout << std::bitset<32>(front_mask) << " = front_mask (bit_mask(16, 16))\n";
    std::cout << std::bitset<32>(back_mask) << " = back_mask (bit_mask(16, 0))\n\n";

    unsigned value = 0;
    std::cout << std::bitset<32>(value) << " = value (initial)\n\n";

    bit_masked_set(value, 1, front_mask, 16);
    std::cout << std::bitset<32>(value) << " = value (after bit_masked_set(value, 1, front_mask, 16))\n\n";

    bit_masked_set(value, 1, back_mask, 0);
    std::cout << std::bitset<32>(value) << " = value (after bit_masked_set(value, 1, back_mask, 0))\n\n";

    std::cout << std::bitset<32>(value) << " = value (final)\n";
}

以下哪项输出:

代码语言:javascript
复制
11111111111111110000000000000000 = front_mask (bit_mask(16, 16))
00000000000000001111111111111111 = back_mask (bit_mask(16, 0))

00000000000000000000000000000000 = value (initial)

00000000000000010000000000000000 = value (after bit_masked_set(value, 1, front_mask, 16))

00000000000000010000000000000001 = value (after bit_masked_set(value, 1, back_mask, 0))

00000000000000010000000000000001 = value (final)

我正在使用带有-Wall -c++17的Visual Studio2017,它对此很满意。但我注意到,当我将其粘贴到godbolt网站上时,gcc/clang/etc给出了警告和/或错误,例如:

代码语言:javascript
复制
error: constexpr variable 'front_mask' must be initialized by a constant expression
...
error: left operand of shift expression '(-1 << 16)' is negative [-fpermissive]
...
etc

由于这些是预处理器宏,它们使用常量值分配给已知的数据类型,所以这不应该是问题。

Edit2:

我尝试了更多,发现将我的bit_mask宏更改为:

代码语言:javascript
复制
#define bit_mask(size, offset) (~((unsigned long long)~0 << size) << offset)

似乎解决了这个问题。我不是100%确定我是否需要额外的long long,但我认为这不会有什么坏处,它会更灵活。

Edit3:

将代码从宏显着更新为简单的结构:

代码语言:javascript
复制
#include <bitset>
#include <iostream>
#include <type_traits>

struct BitMask {
    using Mask_Type = unsigned long long;

    Mask_Type mask;
    unsigned offset;

    constexpr BitMask(unsigned size, unsigned offset) :
        mask{~((Mask_Type)~0 << size) << offset},
        offset{offset} {
    }

    template<typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value, T>::type>
    constexpr T set_bits(T& dst, T src) const {
        return dst = (dst & ~mask) | (src << offset);
    }

    template<typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value, T>::type>
    constexpr T get_bits(T src) const {
        return (src & mask) >> offset;
    }
};

constexpr BitMask front_mask = BitMask(16, 16);
constexpr BitMask back_mask = BitMask(16, 0);

int main() {
    std::cout << std::bitset<32>(front_mask.mask) << " = front_mask (bit_mask(16, 16))\n";
    std::cout << std::bitset<32>(back_mask.mask) << " = back_mask (bit_mask(16, 0))\n\n";

    unsigned value = 0;
    std::cout << std::bitset<32>(value) << " = value (initial)\n\n";

    front_mask.set_bits(value, 1U);
    std::cout << std::bitset<32>(value) << " = value (after bit_masked_set(value, 1, front_mask, 16))\n\n";

    back_mask.set_bits(value, 1U);
    std::cout << std::bitset<32>(value) << " = value (after bit_masked_set(value, 1, back_mask, 0))\n\n";

    std::cout << std::bitset<32>(value) << " = value (final)\n";
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-06-23 17:58:48

因此,既然#define bit_mask(size, offset) (~((unsigned long long)~0 << size) << offset)似乎已经解决了这个问题,我就将其标记为已回答。如果有人发帖说这不是正确的解决方案,他们提供了一些不同的东西,我会接受他们的答案,只要它有效。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56722099

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档