比较C中的负数

ziK*_*ouT 3 c

我对我编写的程序有疑问.该程序将进入if语句,而不应该.我有两个变量:

size_t len = 5;
int    tmp = -1;
Run Code Online (Sandbox Code Playgroud)

当我做 :

if (tmp > len)
    ft_putstr("this is crazy");
Run Code Online (Sandbox Code Playgroud)

我打印出"这很疯狂,而-1比我小5!好的,好的.所以我看了我最喜欢的网站,看到了这个.

尝试时:

printf("%zu", tmp) 
Run Code Online (Sandbox Code Playgroud)

我看到一个很大的正数.好 !这可能是我的程序进入上述if条件的原因,但是如何让它不进入if条件?谢谢

sky*_*ing 5

这里的问题是你试图将未签名的东西与签名的东西进行比较.这意味着在实际转换完成之前涉及隐式转换.在这种情况下,signed会转换为unsigned(通常不是人们想要的) - 因此许多编译器可以选择在完成此操作时显示警告.

要以一种草率的方式做到更正确,你会写:

 if( (int)tmp > (int)len )
Run Code Online (Sandbox Code Playgroud)

然而,这忽略了size_t可能具有太大的值的事实int.要严格,必须要处理的是,范围int与范围相结合size_t可能比任何可用类型都要大.这意味着,你将不得不在两种情况下,以处理这个问题,所以你会用事实,如果tmp<0再tmp<len(数学,因为len>=0).因此,例如在数学tmp<len上将被写为tmp<0 || tmp<len.反之亦然tmp>=0 && tmp >= len.你应该写:

 if( tmp >= 0 && tmp > len )
Run Code Online (Sandbox Code Playgroud)

请注意,转换不是问题,tmp可以在第一次检查后转换为无符号而不更改值,不同的范围int和size_t不是问题,因为较小的值在比较之前转换为更宽的范围.

剩下的唯一问题是,如果你启用了有关无符号签名比较的警告(以检测这些错误),它仍然会发出警告.为了解决这个问题,你需要明确地输入它,但我们知道,tmp一旦我们检查了它,转换为unsigned就不会改变tmp>=0.所以为了避免警告你会写:

if( tmp >= 0 && (unsigned)tmp > len) )
Run Code Online (Sandbox Code Playgroud)

的(unsigned)是,因为tmp是一个int,你需要尊重转化为unsigned如果在类型tmp是另一种类型.


Paw*_*wan 0

您必须了解不同变量类型之间的区别。诸如int、unsigned等变量类型size_t具有不同的行为,并基于此您得到结果。

如果您确实想比较两个数字,它们都必须处于同一级别(变量类型),否则您会得到意想不到的结果。

以下将解决您的问题。

if(tmp > (int)len)
    ft_putstr("this is crazy");
Run Code Online (Sandbox Code Playgroud)

正如 @jblixr 建议的那样(感谢您的评论),您可能需要处理sizeof这些变量类型,并确保在将值从一种数据类型转换为另一种数据类型时不会丢失这些值。

  • 您觉得这是一个好的解决办法吗?如果“len”类似于“4294967295”会发生什么?那么 `len` 将被视为负数。 (3认同)