2

我想提前说,我无法用几行代码重新创建我将要解释的问题(相信我,我试过了)。而且,我已经解决了我在下面描述的问题。我只是想确定它发生的原因。

我正在为 C 编写一个终端代码编辑器 。在另一个架构(具体来说是 Arm)中对其进行测试时,我遇到了一个奇怪的错误——它不再向上滚动(只是向下滚动)。我在这段代码中将问题缩小到这个函数调用main

} else if ((c + 64) == 'V'){
    edit_scroll (&session, session.max_y / 2);
    session.cursor = session.disp;
    session.flags |= EDIT_FLAG_REPRINT;
} else if ((c + 64) == 'Y'){
    //here
    edit_scroll (&session, -1 * (session.max_y / 2)); /*
                                |                 |
        Removing parenthesis causes compilation errors
        in some platforms.
    */
    session.cursor = session.disp;
    session.flags |= EDIT_FLAG_REPRINT;
 }

edit_scroll当向其传递负值时将向上滚动(如图所示)。当我添加这两个括号时,我修复了错误,我发现表达式正在2147483598函数调用中进行计算。请注意,当我运行此测试时int,此编译中的最大值为2,147,483,647且大小为session.max_y100该变量代表终端高度)。

这是edit_scroll实现:

int edit_scroll (struct edit * session, int deltay){
    // I printed deltay at this line, when I determined the value
    int i = session->disp;
    char * data = session->buffer.data;

    if (deltay > 0){
        for (; data[i] && deltay; i++){
            if (data[i] == '\n'){
                deltay--;
            }
        }

        if (!deltay){
            session->disp = i;
        }

    }

    if ((deltay < 0) && (session->disp > 0)){
        for (i--; i > 0; i--){
            if (data[i - 1] == '\n'){
                if (!(++deltay)){
                    break;
                }
            }
        }
        session->disp = i;
    }

    return 0;
}

就像我说的,我无法在小型测试程序中重现此错误。我已经用 Clang 和 Gcc 试过了,它们都给出了同样的错误。为什么这会评估为这样一个奇数?可以肯定地说这是一个编译错误吗?

-1 * session.max_y / 2

向大会展示会有所帮助吗?我应该发布更多源代码吗?我不愿发布整个代码,因为.c仅文件就比1800行多一点。

4

2 回答 2

3

乘法和除法是左结合的。因此,如果您删除括号,您正在计算(-1 * session.max_y) / 2而不是-1 * (session.max_y / 2). 如果该 max_y 字段是无符号的,则该除法将在一种情况下进行符号扩展,而在另一种情况下则不会,从而产生不同的结果。

于 2013-07-31T03:30:25.803 回答
1

不管 的值如何max_y,如果它是无符号的,那么当你将它乘以-1时,它会在乘法发生之前-1转换为unsigned,然后结果是unsigned

我建议在你做任何涉及负数的事情之前抛弃无符号。即使您没有进行除法,在将非常大的无符号结果(应该是负数)转换回有符号类型时,最终也会出现整数溢出和未定义的行为。(我怀疑这种溢出是您看到的编译错误的根源,否则一切都是明确定义的,只是方式错误。)

于 2013-07-31T03:31:29.590 回答