有符号字符的按位运算

时间:2018-06-03 22:18:48

标签: c++

如果平台的char类型已签名且某些参数位于负范围内(例如,char_bitmatch('\xf0', '\xc0', '\x20')),以下代码是否依赖于未定义的行为?

static constexpr bool char_bitmatch(char c, char pos, char neg)
{
    return (c & pos) == pos
        && !(c & neg);
}

上下文

我问这个的原因是因为在GCC 8.1.0中-O3,我看到的行为只能由char_bitmatch('\xf0', '\xc0', '\x20')错误地返回true引起。此代码的行为符合预期:

static constexpr bool char_bitmatch(char c_in, char pos_in, char neg_in)
{
    auto c   = static_cast<unsigned char>(c_in);
    auto pos = static_cast<unsigned char>(pos_in);
    auto neg = static_cast<unsigned char>(neg_in);

    return (c & pos) == pos
        && !(c & neg);
}

根据我的理解,这应该解决了问题 - &应该在signed charunsigned char之间保持一致。

这让我得出了一些结论(但我不知道哪个是正确的):

  1. 使用unsigned char修复了未定义的行为。
  2. 我仍然依赖于未定义的行为 - &#34;修复&#34;很幸运,实际的错误在我的代码中的其他地方。
  3. GCC 8.1.0优化中存在一个错误 - &#34;修复&#34;是一个伏都教咒语,使GCC做正确的事。

1 个答案:

答案 0 :(得分:1)

有趣。我认为你char_bitmatch正在返回true的假设是,呃,是假的。

当我运行此代码时:

#include "stdio.h"

static constexpr bool char_bitmatch(char c, char pos, char neg)
{
    return (c & pos) == pos
        && !(c & neg);
}

int main (void)
{
    constexpr bool b = char_bitmatch ('\xf0', '\xc0', '\x20');
    printf ("%d\n", b);
}

我明白了:

0

所以我认为问题出在代码的其他地方。

我使用了与你相同的编译器 - 在Wandbox运行它(可选择编译器)。

另外,== pos是多余的,不是吗?