C++ 有符号字符的位运算

C++ 有符号字符的位运算,c++,C++,如果平台的char类型已签名且某些参数在负范围内(例如,char\u位匹配('\xf0','\xc0','\x20')),则以下代码是否依赖于未定义的行为 上下文 我问这个问题的原因是因为在带有-O3的GCC 8.1.0中,我看到一种行为只能由char\u位匹配('\xf0','\xc0','\x20')错误返回true引起。此代码的行为符合预期: static constexpr bool char_bitmatch(char c_in, char pos_in, char neg_in)

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


上下文 我问这个问题的原因是因为在带有
-O3
的GCC 8.1.0中,我看到一种行为只能由
char\u位匹配('\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);
}
static constexpr bool char\u bitmatch(char c\u in,char pos\u in,char neg\u in)
{
自动c=静态c_-cast(c_-in);
自动位置=静态浇铸(位置输入);
自动负=静态投切(负投切);
退货(c&pos)=pos
&&!(c&neg);
}
根据我的理解,这不应该解决这个问题--
&
有符号字符
无符号字符
之间应该是一样的

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

  • 使用
    无符号字符
    修复了未定义的行为
  • 我仍然依赖于未定义的行为——“修复”是运气,而实际的bug存在于代码的其他地方
  • GCC 8.1.0优化中有一个bug——“修复”是一个巫毒咒语,它让GCC做正确的事情

  • 有趣。我认为你认为
    char\u 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
    
    所以我认为问题出在代码的其他地方

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


    而且,
    ==pos
    是多余的,不是吗?

    所以每次使用
    &
    操作数都会升级--在这段代码中,它们变成
    int
    。从带符号的
    char
    升级到
    int
    unsigned char
    升级到
    int
    的行为完全不同。@BenVoigt看着代码,这会影响这里的结果吗?@Paul:我不这么认为,但这与问题的说法相反,即“
    &
    在有符号的
    字符和
    无符号的字符之间应该是一样的。”@Ben好的,明白了。我发现你的评论很有教育意义(我从来没有停下来思考过),这让我想到了。
    ==pos
    如果测试是“所有
    pos
    位都设置好了(并且没有任何
    neg
    位设置好了”)。省略
    ==pos
    将导致“设置了任何
    pos
    位…”规则。我在独立娱乐中也看到了这一点。这是一个棘手的问题,因为这个问题只发生在发布版本中,而添加打印语句等操作也会消除这个问题。我的假设只通过GDB得到了验证--
    length==2
    @Ben啊是的,你说得对,我想了一点,对不起。显然,我每天早上都太早了,我经常自己使用这种结构。@Travis-Hmmm,那里有很多代码。足以使我的平板电脑崩溃,但我现在已经确信,
    char\u bitmatch
    与签名字符一样工作,即使我个人不会这样编码,即使我看起来还没有完全清醒!
    0