我应该禁用 C 编译器有符号/无符号不匹配警告吗?

问题描述 投票:0回答:11

当您尝试比较两个变量(其中一个是有符号的,另一个是无符号的)时,Microsoft C 编译器会发出警告。例如:

int a;    
unsigned b;

if ( a < b ) { // warning C4018: '&lt;' : signed/unsigned mismatch

}

这个警告在世界历史上曾经遇到过真正的错误吗?无论如何,为什么它在那里?

c compiler-warnings
11个回答
30
投票

永远不要忽略编译器警告。


25
投票

哦,有。但反过来说。有一天,忽视这个警告让我非常头疼。我正在编写一个绘制图形以及混合有符号和无符号变量的函数。在一个地方,我将负数与无符号数进行了比较:

int32_t t; ...
uint32_t ut; ...

if(t < ut) { 
    ...
}

猜猜发生了什么?有符号数被提升为无符号类型,因此最终变得更大,尽管它最初低于 0。我花了几个小时才发现这个错误。


4
投票

如果您必须问这个问题,您对禁用它是否安全不够了解,所以答案是否定的。

我不会禁用它 - 我不认为我总是比编译器更了解(尤其是因为我经常不知道),更特别的是因为我有时会因疏忽而犯错误,而编译器不知道。


3
投票

应该

a
b
更改为都使用有符号类型,或者都使用无符号类型。 但这可能不切实际(例如,它可能超出您的控制范围)。

警告是为了捕获具有负值的有符号整数和无符号整数之间的比较 - 如果两个数字的大小都很小,则前者将(错误地)被视为大于后者。


2
投票

二元运算符通常在进行比较之前将两种类型转换为相同类型,因为其中一个是无符号的,它也会将 int 转换为无符号。 通常这不会造成太大麻烦,但如果你的 int 是负数,这会导致比较错误。

例如当从有符号转换为无符号时,-1 等于 4294967295,现在将其与 100(无符号)进行比较


2
投票

警告的存在是有目的的......它们会让你认真思考你的代码!

就我个人而言,如果可能的话,我总是会显式地转换签名 --> 未签名和未签名 --> 签名。通过这样做,您可以确保您拥有交易的所有权并且您知道将会发生什么。我意识到这可能并不总是可行,具体取决于执行此操作的项目,但始终以 0 编译器警告为目标......它只会有所帮助!


0
投票

我编写代码的时间比我愿意承认的要长。 根据个人经验,忽略看似迂腐的编译器警告有时会产生非常令人不快的结果。

如果他们惹恼了你,而你接受/理解了这种情况,那么就设定一个角色并继续前进。

最终,这些事情从一个被忽视的细微差别变成了设计新代码时有意识的决定。结果,为 Mickmouse 极端情况破坏您或您的客户的日子留下了更少的空间,并且总体上质量更好的软件。


0
投票

我什至配置了编译器,使该警告成为编译错误。由于所有其他人已经提到的原因。

如果我遇到有符号/无符号不匹配,我会问自己为什么选择不同的“符号”。这通常是一个设计错误。


0
投票

@gimel 关于拍摄链接后面发现的整条腿的解释对于这个问题来说非常好。

-“回避简单问题的人可能只是在走向不那么简单的问题。”

当您在不同类型之间进行转换并且不检查那些可能会伤害您的值时,这实际上总是正确的。

/约翰

更新:从 uint 转换为 int 的正确方法是检查 针对 limit.h 的值,或类似的东西。 (但我自己很少这样做,即使你我知道我应该......:-)


0
投票

我认为最好将您的无符号数转换为有符号数(在比较之前)。 而不是相反。


-1
投票

这只是 C 让您能够 搬起石头砸自己的脚 的众多方式之一 - 您最好知道自己在做什么。 C 的引用出自 Bjarne StroustrupC++ 的创建者。

© www.soinside.com 2019 - 2024. All rights reserved.