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

编译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  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是无符号的,并且由于这个原因,两个整数都将> = 0。 但是因为我从另一个中减去一个,所以我不明白。 为什么会出现这个错误?

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

根据C99标准通用算术转换草案的第6.3.1.8节,由于它们属于同一类型,因此结果也将是size_t 。 该节说明:

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

后来说:

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

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

  n >= i 

考虑这个循环:

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

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

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

unsigned算术结果是unsigned ,这就是你得到这个警告的原因。 最好将n - i >= 0改为n >= i

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