我应该禁用C编译器签名/未签名的不匹配警告吗?

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

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

在世界历史上,这个警告是否曾经发现过一个真正的错误? 无论如何,为什么呢?

哦,它有。 但反过来说。 有一天, 忽略那个警告给我带来了巨大的麻烦。 我正在编写一个绘制图形的函数,并混合有符号和无符号变量。 在一个地方,我将负数与无符号数进行比较:

 int32_t t; ... uint32_t ut; ... if(t < ut) { ... } 

猜猜发生了什么? 已签名的数字被提升为无符号类型,因此最终更大 ,即使它最初低于0。 我花了几个小时才发现了这个漏洞。

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

如果你不得不问这个问题,你就不太了解是否可以安全地禁用它,所以答案是否定的。

我不会禁用它 – 我不认为我总是比编译器更清楚(尤其是因为我经常不这样做),更特别是因为我有时会在编译器没有时通过监督来犯错误。

应该ab更改a使用签名类型,或者两者都使用无符号类型。 但这可能不实用(例如,它可能超出您的控制范围)。

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

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

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

这些警告是出于某种目的……它们会让你仔细思考你的代码!

就个人而言,如果可能的话,我总是明确地将签名 – >无符号和无符号 – >签名。 通过这样做,您确保您拥有交易的所有权,并且您知道将要发生什么。 我意识到它可能并不总是可能的,取决于项目来执行此操作,但总是针对0编译器警告…它只能帮助!

我编写的代码比我想承认的要长。 从个人经验来看,忽略看似迂腐的编译器警告有时会产生非常不愉快的结果。

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

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

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

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

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

– “避免这些简单问题的人可能只是想要一个不那么简单的问题。”

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

/约翰

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

我认为最好将您的未签名号码转换为签名号码(在比较之前)。 而不是相反。

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