运行时错误:负值左移 -1

Posted

技术标签:

【中文标题】运行时错误:负值左移 -1【英文标题】:runtime error: left shift of negative value -1 【发布时间】:2022-01-03 20:59:54 【问题描述】:

其实我正在尝试这个问题:

《Cracking the coding interview:189 Programming questions and Solutions,第五版》中的5.4

问题是:

给定一个正整数,打印在其二进制表示中具有相同数量 1 的下一个最小和下一个最大数字。

有一个确切的same question,但答案都是错误的。 而且,我这个问题的目的是为了理解为什么代码不能通过ub checker,而不仅仅是为了解决问题。

0

leetcode 上的“最后执行的输入”是什么意思?是否是导致错误的输入示例,如果是,为什么即使我打开所有 -Wall,三个编译器也没有警告?

1

这本书为什么错了? 这是书中的代码:


class Solution 
public:
    int getNext(int n)
    
        int c = n;
        int c0 = 0;
        int c1 = 0;
        while (((c & 1) == 0) && (c != 0))
        
            c0++;
            c >>= 1;
        
        while ((c & 1) == 1)
        
            c1++;
            c >>= 1;
        
        if (c0 + c1 == 31 || c0 + c1 == 0)  return -1; 
        int p = c0 + c1;
        n |= (1 << p);
        n &= ~((1 << p) - 1);
        n |= (1 << (c1 - 1)) - 1;
        return n;
    
    int getPrev(int n)
    
        int temp = n;
        int c0 = 0;
        int c1 = 0;
        while ((temp & 1) == 1)
        
            c1++;
            temp >>= 1;
        
        if (temp == 0)return -1;
        while (((temp & 1) == 0 )&& (temp != 0))
        
            c0++;
            temp >>= 1;
        
        int p = c0 + c1;
        n &= ((~0) << (p + 1));
        int mask = (1 << (c1 + 1)) - 1;
        n |= mask << (c0 - 1);
        return n;
    
    vector<int> findClosedNumbers(int num) 
        int m = getNext(num);
        int n = getPrev(num);
        return m,n;
    
;

错误输出是

Line 43: Char 14: runtime error: left shift of negative value -1 (solution.cpp)
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior prog_joined.cpp:53:14

我找到this,它说“左移负值是未定义的行为”

但是为什么我在https://godbolt.org/ 使用了我能想到的所有墙旗,但我没有得到任何提示。 是否有一些标志可以像 UndefinedBehaviorSanitizer 一样显示?

2.

某人的answer不能通过

这个答案中提到的链接不能通过lc,这是什么问题?

代码:


class Solution 
public:
    vector<int> findClosedNumbers(int num) 
        int m = getNextLarger(num);
        int n = getNextSmaller(num);
        return  m,n ;
    
    int getNextLarger(int num) 
        if (num == 0 || num == -1)
            return num;

        // (1) add 1 to the last set bit
        int largeNum = num + (num & ~(num - 1));

        // (2) move the changed bits to the least significant bits. (right side)
        int flipBits = num & ~largeNum;
        int lastBits = 0;
        while (flipBits != 0) 
            flipBits &= flipBits - 1;
            lastBits <<= 1;
            lastBits |= 1;
        
        lastBits >>= 1;

        // (2.1) move bits to maintain the same number of set bits.
        largeNum |= lastBits;
        return largeNum;
    
    //Unhandled exception at 0x0033F4B9 in leetcode.exe: 0xC00000FD: Stack overflow 
    int getNextSmaller(int num)    //with num=2
        return ~getNextLarger(~num);
    
;

【问题讨论】:

有符号整数值的左移是根据 C++ 标准的未定义行为。就那么简单。您可以通过首先转换为相同大小的无符号值来修复它,或者您找出一种不会改变有符号值的不同方法。 @LouisCloete Left shift of a signed integer value is undefined behaviour 你不是说“负整数”吗?只要操作数在允许的域内,有符号移位就可以很好地定义。 “破解编码面试”并不是 C++ 编码的巅峰之作。那里的大部分代码实际上都很糟糕。 从标题中已经很清楚了:runtime error 不是编译器在编译时就知道的东西 对于“堆栈溢出”问题,您输入了错误的代码。应该是~getNextLarger(~num),而不是调用getNextSmaller 【参考方案1】:

为什么 func 可以传入 msvc、clang 和 gcc,但不能通过 UndefinedBehaviorSanitizer?

因为编译器在编译时不知道操作数在运行时的值是多少。如果编译器能够在编译时检测到所有 UB,那么 UB sanitisers 就不会存在,因为它们是不必要的。

【讨论】:

如果编译器可以在编译时检测到所有的UB,我们就可以解决停机问题,逻辑本身就会燃烧起来。

以上是关于运行时错误:负值左移 -1的主要内容,如果未能解决你的问题,请参考以下文章

Uipath 鼠标点击光标偏移的使用

为啥逻辑左移与算术左移相同?

音频波形中负值的含义

为啥返回负值

CoreLocation 负值

vertical-align负值和margin-bottom负值的区别