15

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

int a;    
unsigned b;

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

}

在世界历史上,这个警告有没有发现过真正的错误?为什么它在那里?

4

11 回答 11

30

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

于 2009-02-05T13:08:06.930 回答
24

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

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

if(t < ut) { 
    ...
}

猜猜发生了什么?有符号数被提升为无符号数,因此最终更大,即使它最初低于 0。我花了几个小时才找到错误。

于 2009-02-05T13:07:03.250 回答
4

如果你要问这个问题,你对禁用它是否安全知之甚少,所以答案是否定的。

我不会禁用它——我不认为我总是比编译器更了解(尤其是因为我经常不这样做),尤其是因为我有时会在编译器不知道的情况下因疏忽而犯错误。

于 2009-02-06T03:37:09.560 回答
3

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

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

于 2009-02-05T13:06:01.783 回答
2

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

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

于 2009-02-05T13:06:23.623 回答
2

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

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

于 2009-02-05T13:16:55.677 回答
0

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

如果他们惹恼了你并且你接受/理解了这种情况,那么设置一个演员并继续前进。

最终,在设计新代码时,这些事情会从被忽视的细微差别转变为有意识的决定。结果为 mickmouse 角落案例留下了更少的空间来破坏您或您的客户的一天和整体质量更好的软件。

于 2009-02-07T03:53:46.093 回答
0

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

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

于 2009-02-07T08:08:09.873 回答
0

@gimel关于拍摄整个链接背后的整个腿的解释对于这个问题非常有用。

——“回避简单问题的人可能只是朝着不那么简单的问题前进。”

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

/约翰

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

于 2009-02-07T08:15:51.587 回答
0

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

于 2009-11-02T20:14:01.707 回答
-1

这只是C允许你在脚上射击自己的众多方式之一 ——你最好知道自己在做什么。C的引用归功于C++的创建者Bjarne Stroustrup

于 2009-02-05T13:36:34.093 回答