对理解和消除 -Wsign-compare gcc 的警告感到困惑
Confused about understanding and silencing a -Wsign-compare gcc's warning
这是我正在尝试编译的函数:
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
也是无符号的。我现在认为我错了,但我真的不明白为什么。
此外,你能给我一些提示让我闭嘴吗?
这个表达式与您的想法不符:
(size -= write(buf->fd, src, size) < osize)
小于运算符 <
的优先级高于复合赋值运算符 -=
。所以上面的解析为:
(size -= (write(buf->fd, src, size) < osize))
所以这比较了类型为 ssize_t
的 write
和类型为 size_t
的 osize
的输出。这是 signed/unsigned 比较发生的地方。然后从 size
中减去此比较的结果,因此它每次只会减 1。
在作业周围添加括号:
((size -= write(buf->fd, src, size)) < osize)
警告将消失,因为您现在正在比较 size_t
和 size_t
。
但是还有另一个问题。如果 write
returns -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;
}
我认为您遇到了运算符优先级问题。您的代码被解释为:
&& (size -= (write(buf->fd, src, size) < osize)))
因此,您可以通过强制使用所需的优先级来修复它:
&& ((size -= write(buf->fd, src, size)) < osize))
警告通过指出问题来帮助您,如果您不完全理解警告,切勿将警告静音。
此外,在条件中使用副作用是不好的做法。如果将赋值运算符 -=
移到条件之外,您的代码将更易于理解和维护。
这是我正在尝试编译的函数:
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
也是无符号的。我现在认为我错了,但我真的不明白为什么。
此外,你能给我一些提示让我闭嘴吗?
这个表达式与您的想法不符:
(size -= write(buf->fd, src, size) < osize)
小于运算符 <
的优先级高于复合赋值运算符 -=
。所以上面的解析为:
(size -= (write(buf->fd, src, size) < osize))
所以这比较了类型为 ssize_t
的 write
和类型为 size_t
的 osize
的输出。这是 signed/unsigned 比较发生的地方。然后从 size
中减去此比较的结果,因此它每次只会减 1。
在作业周围添加括号:
((size -= write(buf->fd, src, size)) < osize)
警告将消失,因为您现在正在比较 size_t
和 size_t
。
但是还有另一个问题。如果 write
returns -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;
}
我认为您遇到了运算符优先级问题。您的代码被解释为:
&& (size -= (write(buf->fd, src, size) < osize)))
因此,您可以通过强制使用所需的优先级来修复它:
&& ((size -= write(buf->fd, src, size)) < osize))
警告通过指出问题来帮助您,如果您不完全理解警告,切勿将警告静音。
此外,在条件中使用副作用是不好的做法。如果将赋值运算符 -=
移到条件之外,您的代码将更易于理解和维护。