警告:无符号表达式> = 0的比较始终为true

时间:2013-11-19 14:24:20

标签: c gcc

编译C文件时出现以下错误:

t_memmove.c: In function ‘ft_memmove’:
ft_memmove.c:19: warning: comparison of unsigned expression >= 0 is always true

以下是完整代码,来自cat ft_memmove.c

#include "libft.h"
#include <string.h>

void    *ft_memmove(void *s1, const void *s2, size_t n)
{
    char    *s1c;
    char    *s2c;
    size_t  i;

    if (!s1 || !s2 || !n)
    {
        return s1;
    }
    i = 0;
    s1c = (char *) s1;
    s2c = (char *) s2;
    if (s1c > s2c)
    {
        while (n - i >= 0) // this triggers the error
        {
            s1c[n - i] = s2c[n - i];
            ++i;
        }
    }
    else
    {
        while (i < n)
        {
            s1c[i] = s2c[i];
            ++i;
        }
    }
    return s1;
}

我确实理解size_t是无符号的,并且由于这个原因,两个整数都将是&gt; = 0。但是因为我从另一个中减去一个,所以我不明白。为什么会出现这个错误?

5 个答案:

答案 0 :(得分:19)

如果在C中减去两个无符号整数,结果将被解释为无符号。它不会因为您减去而自动将其视为已签名。解决此问题的一种方法是使用n >= i而不是n - i >= 0

答案 1 :(得分:2)

根据C99标准常规算术转换草案的6.3.1.8部分,由于它们属于同一类型,因此结果也为size_t。该部分说明:

  

[...]除非另有明确说明,否则常见的实际类型也是结果的相应实际类型[...]

后来说:

  

如果两个操作数具有相同的类型,则不需要进一步转换。

在数学上你可以将i移到表达式的另一边,如下所示:

 n >= i

答案 2 :(得分:2)

考虑这个循环:

for(unsigned int i=5;i>=0;i--)
{

}

这个循环将是无限的,因为每当我变为-1时,它将作为一个非常大的正确值被插入,因为unsigned int中没有符号位。

这就是在这里产生警告的原因

答案 3 :(得分:0)

unsigned上的算术会产生unsigned,这就是您收到此警告的原因。最好将n - i >= 0更改为n >= i

答案 4 :(得分:0)

无符号操作数的操作在无符号类型的域中执行。无符号算术遵循模运算的规则。这意味着即使你从某些东西中减去某些东西,结果永远也不会是负面的。例如,1u - 5u不会生成-4。如果生成UINT_MAX - 3,这是一个与-4UINT_MAX + 1一致的巨大正值。