2016-01-29 166 views
3

我遇到了我写的程序有问题。该程序将进入if语句,而不应该。 我有两个变量:比较C中的负数

size_t len = 5; 
int tmp = -1; 

当我做!。

if (tmp > len) 
    ft_putstr("this is crazy"); 

我打印出“这太疯狂了,而-1小于5我 好吧,好吧,所以我看着我最喜欢的网站,看到this

当尝试:

printf("%zu", tmp) 

我看到一个很大的正数。好 !这可能是为什么我的程序进入if条件的原因,但我怎么能使它不进入if条件?谢谢

+4

这是因为'size_t'是一个无符号整数类型,所以当比较一个有符号整数类型时,就会执行无符号比较。 –

+1

尝试'if(tmp> 0 && tmp> len)' – user3386109

+0

'printf(“%zu”,tmp);'会导致未定义的行为。使用'printf',您可以使用正确的格式说明符。 –

回答

0

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

如果你真的想比较两个数字,他们都必须在同一水平(变量类型),否则你会得到意想不到的结果。

以下将解决您的问题。

if(tmp > (int)len) 
    ft_putstr("this is crazy"); 

由于@jblixr建议(对于评论的感谢),你可能要采取sizeof这些变量类型的照顾,并确保当从一种数据类型转换值到另一种数据类型的值不被丢失。

+3

你认为这是一个很好的解决方案啊?如果'len'与'4294967295'类似,会发生什么?那么'len'将被视为负数。 –

+0

@jblixr如果您指的是sizeof'size_t'和'int';没有。 – Pawan

+1

“size_t”值大于“INT_MAX”的可能性有多大?不是特别的。这种比较在大多数情况下都很好。 –

5

这里的问题是,你正试图比较一些未签名的东西和已签名的东西。这意味着在实际转换完成之前有一个隐式转换。在这种情况下,signed被转换为unsigned(这通常不是人们想要的 - 因此许多编译器可以选择在完成时显示警告)。

要做到这一点你会写一个草率的方式比较正确:

if((int)tmp > (int)len) 

但是这忽略了一个事实size_t可以有一个是int值过大。严格来说,必须处理intsize_t的范围相结合的范围可以大于任何可用的类型。这意味着你将不得不在两种情况下处理这个问题,所以你会使用这个事实,即如果tmp<0那么tmp<len(数学上,因为len>=0)。因此,例如在数学上tmp<len将被写为tmp<0 || tmp<len。而相反的是tmp>=0 && tmp >= len。因此,你应该写:

if(tmp >= 0 && tmp > len) 

注意,则转换是没有问题的,tmp可以在第一次检查后转换为无无值改变,intsize_t不同范围也不是问题作为比较之前,较小者转换为较宽范围。

剩下的唯一问题是,如果您启用了关于带符号无符号比较的警告(以检测这些类型的错误),它仍会警告。为了照顾到这一点,您需要明确地输入它,但是我们知道一旦我们检查了tmp>=0,转换为无符号不会改变tmp。因此,为了避免警告你可以这样写:

if(tmp >= 0 && (unsigned)tmp > len)) 

(unsigned)是因为tmpint,你需要转换为无符号时,如果tmp是另一种类型的尊重类型。