简体   繁体   English

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

[英]Is this an unavoidable signed and unsigned integer comparison?

Probably not, but I can't think of a good solution. 可能不是,但是我想不出一个好的解决方案。 I'm no expert in C++ yet. 我还不是C ++专家。

Recently I've converted a lot of int s to unsigned int s in a project. 最近,我在项目中将很多int转换为unsigned int Basically everything that should never be negative is made unsigned. 基本上,所有不应为负的内容都将变为无符号。 This removed a lot of these warnings by MinGW: 这消除了MinGW的许多警告:

warning: comparison between signed and unsigned integer expressions [-Wsign-compare] 警告:有符号和无符号整数表达式之间的比较[-Wsign-compare]

I love it. 我喜欢它。 It makes the program more robust and the code more descriptive. 它使程序更健壮,代码更具描述性。 However, there is one place where they still occur. 但是,它们仍然存在于一个地方。 It looks like this: 看起来像这样:

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.
    }
}

In this case I can't make dx and dy unsigned. 在这种情况下,我无法使dxdy无符号。 They start out negative and depend on comparing which is lesser or greater. 他们开始时是负面的,并依赖于比较哪个更大或更小。

I don't like to make subroutine_point_size signed either, though this is the lesser evil. 我也不喜欢使subroutine_point_size签名,尽管这是次要的邪恶。 It indicates a size of a kernel in a pass over an image, and the kernel size can't be negative (it's probably unwise for a user ever to set this kernel size to anything more than 100 but the settings file allows for numbers up to 2^32 - 1). 它表示通过图像时内核的大小,并且内核大小不能为负(用户将内核大小设置为大于100可能是不明智的,但是设置文件允许最大为2 ^ 32-1)。

So it seems there is no way to cast any of the variables to fix this. 因此,似乎没有办法强制转换任何变量来解决此问题。 Is there a way to get rid of this warning and solve this neatly? 有没有办法摆脱这种警告并巧妙地解决这个问题?

We're using C++11, compiling with GCC for Windows, Mac and various Unix distributions. 我们使用的是C ++ 11,可与Windows,Mac和各种Unix发行版的GCC一起编译。

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

Instead of the current 代替当前

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

you can do this: 你可以这样做:

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

where the first int cast is (1) technically redundant, but is there for consistency, because the second cast removes the signed/unsigned warning that presumably is the issue here. 其中第一个int强制转换在技术上是(1)冗余的,但出于一致性考虑,因为第二个强制转换删除了可能是此处问题的带符号/无符号警告。

However, I strongly advise you to undo the work of converting signed to unsigned types everywhere. 但是,我强烈建议您撤消将无符号类型转换为无符号类型的工作。 A good rule of thumb is to use signed types for numbers , and unsigned types for bit level stuff . 一个好的经验法则是对数字使用带符号的类型,对位级别的东西使用无符号的类型。 That avoids the problems with wrap-around due to implicit conversions, where eg std:.string("Bah").length() < -5 is guaranteed (very silly), and because it does away with actual problems, it also reduces spurious warnings. 这样可以避免隐式转换带来的环绕问题,例如,保证std:.string("Bah").length() < -5 (非常愚蠢),并且由于它消除了实际问题,因此还减少了虚假警告。

Note that you can just define a suitable name, where you want to indicate that some value will never be negative. 请注意,您可以只定义一个合适的名称,以表示某些值永远不会为负。


1) Technically redundant in practice , for two's complement representation of signed integers, with no trapping inserted by the compiler. 1) 在实践中在技术上是多余 ,对于带符号整数的二进制补码表示,编译器不插入任何陷阱。 As far as I know no extant C++ compiler behaves otherwise. 据我所知,没有现存的C ++编译器有其他行为。

You're making a big mistake. 您犯了一个大错误。

Basically you like the name "unsigned" and you intend it to mean "not negative" but this is not what is the semantic associated to the type. 基本上,您喜欢名称“ unsigned”,并且您希望它的意思是“ not negative”,但这不是与该类型关联的语义。

Consider the statement: 考虑以下语句:

adding a signed integer and an unsigned integer the result is unsigned 将有符号整数和无符号整数相加,结果是无符号的

Clearly it makes no sense if you consider the term "unsigned" as "not negative", yet this is what the language does: adding -3 to the unsigned value 2 you will get a huge nonsense number instead of the correct answer -1. 显然,如果您将术语“无符号”视为“不是负数”是没有意义的,但是这就是语言的作用:在无符号值2上加上-3会得到一个巨大的废话号码,而不是正确的答案-1。

Indeed the choice of using an unsigned type for the size of containers is a design mistake of C++, a mistake that is too late to fix now because of backward compatibility. 确实,选择使用无符号类型作为容器的大小是C ++的设计错误,由于向后兼容性,现在已无法解决此错误。 By the way the reason it happened has nothing to do with "non-negativeness", but just with the ability to use the 16th bit when computers were that small (ie being able to use 65535 elements instead of 32767). 顺便说一下,它发生的原因与“非负数”无关,而只是在计算机很小的情况下才能够使用第16位(即能够使用65535个元素而不是32767个元素)。 Even back then I don't think the price of wrong semantic was worth the gain (if 32767 is not enough now then 65535 won't be enough quite soon anyway). 即使在那时,我也不认为错误语义的代价值得(如果现在32767还不够,那么65535很快就还不够)。

Do not repeat the same mistake in your programs... the name is irrelevant, what counts is the semantic and for unsigned in C and C++ it is "member of the Z n modulo ring with n=2 k ". 不要在您的程序中重复相同的错误...名称无关紧要,重要的是语义,对于C和C ++中的unsigned ,它是“ Z n模环为n = 2 k的成员 ”。

You don't want the size of a container to be the member of a modulo ring. 您不希望容器的大小成为模数环的成员。 Do you? 你呢?

Firstly, without knowing the range of values that will be stored in the variables, your claim that changing signed to unsigned variables is unsubstantiated - there are circumstances where that claim is false. 首先,在不知道将存储在变量中的值的范围的情况下,您声称将有符号的变量更改为无符号的变量的说法不成立-在某些情况下该声明为假。

Second, the compiler is not issuing a warning only as a result of changing variables (and I assume calls of template functions like settings.get() ) to be unsigned. 其次,编译器不会仅由于更改变量(并且我假设调用settings.get()类的模板函数settings.get()的结果而发出警告。 It is warning about the fact you have expressions involving both signed and unsigned variables. 这是对以下事实的警告:您的表达式同时包含有符号和无符号变量。 Compilers typically issue warnings about such expressions because - in practice - they are more likely to indicate a programming error or to potentially involve some behaviour that the programmer may not have anticipated (eg instances of undefined behaviour, expressions where a negative result is expected but a large positive result is what will occur, etc). 编译器通常会发出有关此类表达式的警告,因为-在实践中-它们更有可能指示编程错误或潜在地涉及程序员可能未曾预料到的某些行为(例如,不确定行为的实例,预期结果为负但表达式为负的表达式)将会产生很大的积极结果,等等)。

A rule of thumb is that, if you need to have expressions involving both signed and unsigned types, you are better off making all the relevant variables signed. 一条经验法则是,如果需要同时包含有符号和无符号类型的表达式,最好对所有相关变量进行签名。 While there are exceptions where that rule of thumb isn't needed, you wouldn't have asked this question if you understood how to decide that. 尽管在某些情况下不需要该经验法则,但是如果您了解如何决定的话,就不会问这个问题。

On that basis, I suggest the most appropriate action is to unwind your changes. 在此基础上,我建议最适当的操作是撤销更改。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 警告:有符号和无符号整数表达式之间的比较 - Warning: Comparison between signed and unsigned integer expression 警告 - 有符号和无符号整数表达式之间的比较 - A warning - comparison between signed and unsigned integer expressions 有符号和无符号整数表达式的比较 - Comparison between signed and unsigned integer expressions 有符号和无符号整数表达式S之间的比较 - Comparison between signed and unsigned integer expressions S 查找文件中最长的行,有符号和无符号整数表达式之间的比较 - Finding the longest line in a file, Comparison between signed and unsigned integer expressions 循环错误的有符号和无符号整数表达式的比较 - Comparison between signed and unsigned integer expression for loop error 警告:有符号和无符号整数表达式之间的比较 [-Wsign-compare] - warning: comparison between signed and unsigned integer expressions [-Wsign-compare] 消除有符号和无符号整数表达式之间比较的绝佳方法 - Elegant way to get rid of comparison between signed and unsigned integer expressions 警告:有符号和无符号整数表达式之间的比较..如何解决? - warning: comparison between signed and unsigned integer expressions..how to solve it? 有符号和无符号整数表达式与0x80000000之间的比较 - comparison between signed and unsigned integer expressions and 0x80000000
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM