警告 – 有符号和无符号整数expression式之间的比较

我目前正在使用Accelerated C ++,并且在练习2-3中遇到了一个问题。

该程序的快速概览 – 该程序基本上是一个名字,然后在星号框架内显示一个问候 – 即你好! 周围被*的框架。

练习 – 在示例程序中,作者使用const int来确定问候与星号之间的填充(空格)。 然后他们要求读者作为练习的一部分,要求用户input他们想填充的大小。

所有这些似乎都很简单,我继续向用户询问两个整数( int )并存储它们,然后改变程序使用这些整数,在编译时除去作者使用的整数,虽然我得到以下警告;

Exercise2-3.cpp:46:警告:有符号和无符号整数expression式之间的比较

经过一番研究,似乎是因为代码尝试将上述整数( int )中的一个与string::size_type ,这很好。 但我想知道 – 这是否意味着我应该将其中一个整数更改为unsigned int ? 明确说明我的整数是有符号还是无符号是重要的?

  cout << "Please enter the size of the frame between top and bottom you would like "; int padtopbottom; cin >> padtopbottom; cout << "Please enter size of the frame from each side you would like: "; unsigned int padsides; cin >> padsides; string::size_type c = 0; // definition of c in the program if (r == padtopbottom + 1 && c == padsides + 1) { // where the error occurs 

上面是代码的相关位, c的types是string::size_type因为我们不知道问候可能会持续多长时间 – 但是为什么现在我得到这个问题,当作者的代码在使用时没有遇到问题const int ? 另外,对于任何可能已经完成Accelerated C ++的人来说,这些都会在后面的章节中解释。

我在Linux Mint上使用g ++通过Geany,如果这有助于或有所作为(因为我读它可以确定什么string::size_type )。

将variables声明为unsignedsize_t通常是一个好主意,如果将它们与大小进行比较,可以避免这个问题。 只要有可能,请使用您将要比较的确切types(例如,与std::string的长度进行比较时,使用std::string::size_type )。

编译器给出了有关比较有符号和无符号types的警告,因为有符号和无符号整数的范围是不同的,当它们相互比较时,结果可能会令人惊讶。 如果您必须进行这样的比较,您应该明确地将其中一个值转换为与另一个types兼容的types,可能在检查后确保转换是有效的。 例如:

 unsigned u = GetSomeUnsignedValue(); int i = GetSomeSignedValue(); if (i >= 0) { // i is nonnegative, so it is safe to cast to unsigned value if ((unsigned)i >= u) iIsGreaterThanOrEqualToU(); else iIsLessThanU(); } else { iIsNegative(); } 

我昨天在加速C ++中遇到了问题2-3的问题。 关键是要将所有将要比较的variables(使用布尔运算符)更改为兼容的types。 在这种情况下,这意味着string::size_type (或unsigned int ,但由于这个例子是使用前者,我会坚持,即使两者在技术上是兼容的)。

请注意,在他们的原始代码中,他们正是为c计数器(本书第2.5节中的第30页)做了这一点,正如你正确地指出的那样。

是什么让这个例子更复杂的是,不同的填充variables(padsides和padtopbottom),以及所有的计数器, 必须改为string::size_type

进入你的例子,你发布的代码最终会看起来像这样:

 cout << "Please enter the size of the frame between top and bottom"; string::size_type padtopbottom; cin >> padtopbottom; cout << "Please enter size of the frame from each side you would like: "; string::size_type padsides; cin >> padsides; string::size_type c = 0; // definition of c in the program if (r == padtopbottom + 1 && c == padsides + 1) { // where the error no longer occurs 

请注意,在前面的条件中,如果您没有在for循环中将variablesr初始化为string::size_type ,则会得到错误。 所以你需要使用如下的东西来初始化for循环:

  for (string::size_type r=0; r!=rows; ++r) //If r and rows are string::size_type, no error! 

所以,基本上,一旦你引入了一个string::size_typevariables到混合中,任何时候你想对这个item执行一个布尔运算,所有的操作数都必须有一个兼容的types才能编译而不需要警告。

有符号和无符号整数之间的重要区别是对最后一位的解释。 签名types中的最后一位表示数字的符号,意思是:例如:

0001是1有符号,无符号1001是-1有符号,9是无符号

(为了解释清楚,我避免了整个补充问题!这不完全是如何在内存中表示整数!)

你可以想象,如果你比较-1还是+9,这是有区别的。 在很多情况下,程序员都懒得把unsigned int列为unsigned(扩展for循环头文件)通常这不是一个问题,因为在int中你必须计数到2 ^ 31,直到你的符号位咬你。 这就是为什么它只是一个警告。 因为我们懒得写'unsigned'而不是'int'。

在极端的范围内,unsigned int可以变得比int大。
因此,编译器会生成警告。 如果您确定这不是问题,请随意将types转换为相同的types,以便警告消失(使用C ++types转换以便于识别)。

或者,使variables为相同的types来阻止编译器投诉。
我的意思是,有可能有一个负填充? 如果是的话就把它保存为int。 否则,你应该使用unsigned int,让stream捕获用户input负数的情况。

或者使用这个头文件库并写入:

 // |notEqaul|less|lessEqual|greater|greaterEqual if(sweet::equal(valueA,valueB)) 

不关心签名/未签名或不同的大小