这是不可避免的有符号和无符号整数比较吗?



可能不是,但我想不出一个好的解决方案。我还不是C++方面的专家。

最近,我在一个项目中将很多int转换为unsigned int。基本上,所有不应该是负面的东西都是无符号的。这删除了MinGW的许多警告:

警告:有符号和无符号整数表达式之间的比较 [-Wsign-compare]

我喜欢。它使程序更健壮,代码更具描述性。但是,有一个地方它们仍然发生。它看起来像这样:

unsigned int subroutine_point_size = settings->get<unsigned int>("subroutine_point_size");
...
for(int dx = -subroutine_point_size;dx <= subroutine_point_size;dx++) //Fill pixels in the point's radius.
{
    for(int dy = -subroutine_point_size;dy <= subroutine_point_size;dy++)
    {
        //Do something with dx and dy here.
    }
}

在这种情况下,我无法dxdy未签名。它们一开始是负面的,取决于比较哪个更小或更大。

我也不喜欢让subroutine_point_size签名,尽管这是较小的邪恶。它指示通过图像传递的内核大小,并且内核大小不能为负数(用户将此内核大小设置为大于 100 可能是不明智的,但设置文件允许最多 2^32 - 1 的数字)。

因此,似乎没有办法转换任何变量来解决此问题。有没有办法摆脱这个警告并巧妙地解决这个问题?

我们正在使用C++11,使用GCC编译Windows,Mac和各种Unix发行版。

将变量转换为 long intlong long int 类型,同时给出无符号 int (0..2^32-1) 和符号的范围。

你犯了一个大错误。

基本上,您喜欢名称"无符号",并且您打算将其表示"不负数",但这不是与类型相关的语义。

考虑以下语句:

添加有符号整数和无符号

整数,结果为无符号

显然,如果您将术语"无符号"

视为"非负数",这是没有意义的,但这就是该语言所做的:将 -3 添加到无符号值 2 上,您将获得一个巨大的废话数字而不是正确答案 -1。

事实上,选择使用无符号类型作为容器的大小是C++的设计错误,由于向后兼容性,这个错误现在修复为时已晚。顺便说一下,它发生的原因与"非负性"无关,而只是与计算机那么小时使用第 16 位的能力有关(即能够使用 65535 个元素而不是 32767)。即使在那时,我也不认为错误语义的代价值得获得(如果现在 32767 还不够,那么 65535 无论如何都不会很快足够)。

不要在你的程序中重复同样的错误...名称无关紧要,重要的是语义,对于 C 和C++中的unsigned,它是"n n 模环的成员,n=2k"。

您不希望容器的大小成为模环的成员。是吗?

而不是当前的

for(int dx = -subroutine_point_size;dx <= subroutine_point_size;dx++) //Fill pixels in the point's radius.

您可以这样做:

for(int dx = -int(subroutine_point_size);dx <= int(subroutine_point_size);dx++) //Fill pixels in the point's radius.

其中第一个int转换在技术上是多余的,但是为了保持一致性,因为第二个转换删除了签名/未签名的警告,这可能是这里的问题。

但是,我强烈建议您在任何地方撤消将有符号类型转换为无符号类型的工作。一个好的经验法则是对数字使用有符号类型,对位级的东西使用无符号类型。这避免了由于隐式转换而导致的环绕问题,例如 std:.string("Bah").length() < -5是有保证的(非常愚蠢),并且因为它消除了实际问题,所以它还减少了虚假警告。

请注意,您可以只定义一个合适的名称,您希望在其中指示某个值永远不会为负数。


1)在实践中技术上是多余的,对于有符号整数的二进制补码表示,编译器没有插入陷阱。据我所知,没有现存的C++编译器的行为是其他的。

首先,在不知道将存储在变量中的值范围的情况下,您声称将有符号变量更改为无符号变量是没有根据的 - 在某些情况下,该声明是错误的。

其次,编译器不会仅仅因为更改变量(我假设像settings.get()这样的模板函数的调用)而发出警告是无符号的。 它警告您具有同时涉及有符号和无符号变量的表达式。 编译器通常会发出有关此类表达式的警告,因为在实践中,它们更有可能指示编程错误或可能涉及程序员可能没有预料到的某些行为(例如,未定义行为的实例,预期为负结果但将会发生大量正结果的表达式等)。

经验法则是,如果您需要同时涉及有符号和无符号类型的表达式,则最好使所有相关变量都进行签名。 虽然也有不需要该经验法则的例外情况,但如果您了解如何决定这一点,您就不会问这个问题。

在此基础上,我建议最合适的行动是解除您的更改。

相关内容

  • 没有找到相关文章

最新更新