编译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。但是因为我从另一个中减去一个,所以我不明白。为什么会出现这个错误?
答案 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
,这是一个与-4
模UINT_MAX + 1
一致的巨大正值。