对理解和消除-Wsign-compare gcc警告有疑惑

3

这是我正在尝试编译的一个函数:

static ssize_t  output(t_out_buffer *buf, char const *src, size_t size)
{
        size_t  osize;

        osize = size;
        while ((size > 0)
               && (size -= write(buf->fd, src, size) < osize))
        {
                src += osize - size;
                buf->count +=  osize - size;
                osize = size;
        }
        if (osize < size)
                return (T_OUT_BUFFER_ERROR);
        else
                return (buf->count);
}

gcc会抱怨:

t_out_buffer.c:11:42: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
    && (size -= write(buf->fd, src, size) < osize))
                                          ^

我曾认为,由于 size 是无符号的,所以 size -= whateverintiwant 也应该是无符号的,因为 osize 也是无符号的。但我现在认为我是错的,但我并不真正理解为什么。 此外,你能给我一些提示来消除这个问题吗?


3
如果write()返回值为-1,那么这段代码将会崩溃,因此你需要进行重写。请注意不要改变原意。 - Nate Eldredge
如果write返回-1,size不仅仅会增加一个? - Dadam42
2
是的,它会增加一,而那绝对不是你想要的。 - Nate Eldredge
这绝对是我想要的 ^^ - Dadam42
4
愿上帝怜悯你的灵魂。 - Nate Eldredge
2个回答

8

这个表达式不是你想的那样:

(size -= write(buf->fd, src, size) < osize)

小于运算符<的优先级高于复合赋值运算符-=。因此,上面的代码解析为:
(size -= (write(buf->fd, src, size) < osize))

所以这里将write的输出(类型为ssize_t)与osize(类型为size_t)进行比较,这就是有符号/无符号比较发生的地方。然后将此比较结果从size中减去,因此它每次只会减少1。
在赋值周围添加括号:
((size -= write(buf->fd, src, size)) < osize)

现在你正在比较一个 size_t 与另一个 size_t,警告将消失。

然而还有另一个问题。如果 write 返回 -1,则会执行减法操作,即添加 1。

应该重构代码,使其在循环内进行读取,并且仅在成功读取后才添加结果。

    while (size > 0) {
    {
            ssize_t rval = write(buf->fd, src, size);
            if (rval == -1) {
                return T_OUT_BUFFER_ERROR;
            }
            size -= rval;
            src += rval;
            buf->count +=  rval;
    }

啊,我没看到你的回答,我太慢了!我很惊讶你在6分钟内就想出了这样复杂的答案! - Michele Dorigatti

3

我认为你的代码存在运算符优先级问题。你的代码被解释为:

&& (size -= (write(buf->fd, src, size) < osize)))

因此,您可以通过强制所需优先级来修复它:
&& ((size -= write(buf->fd, src, size)) < osize))

警告是通过指出问题来帮助您的,如果您不完全理解它,您不应该忽略警告。
此外,在条件语句中使用副作用是一种不好的做法。如果您将赋值运算符-=移到条件之外,您的代码将更易于理解和维护。

好的,我会将它移出去。 - Dadam42
我很高兴我的回答不是完全没用的 :) - Michele Dorigatti

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接