Una advertencia: comparación entre expresiones enteras con signo y sin signo

Actualmente estoy trabajando con Accelerated C ++ y me he encontrado con un problema en el ejercicio 2-3.

Una descripción general rápida del progtwig : básicamente, el progtwig toma un nombre, luego muestra un saludo dentro de un marco de asteriscos, es decir, ¡Hola! rodeado enmarcado por * ‘s.

El ejercicio : en el progtwig de ejemplo, los autores usan const int para determinar el relleno (espacios en blanco) entre el saludo y los asteriscos. Luego, le piden al lector, como parte del ejercicio, que pregunte al usuario por qué tan grande quiere que sea el relleno.

Todo esto parece bastante fácil, le pido al usuario dos enteros ( int ) y los guardo y cambio el progtwig para usar estos enteros, eliminando los que usa el autor, pero al comstackr recibo la siguiente advertencia;

Exercise2-3.cpp: 46: warning: comparación entre expresiones enteras con signo y sin signo

Después de algunas investigaciones, parece ser porque el código intenta comparar uno de los enteros anteriores ( int ) con una string::size_type , que está bien. Pero me preguntaba: ¿significa esto que debería cambiar uno de los enteros a unsigned int ? ¿Es importante indicar explícitamente si mis enteros están firmados o no?

  cout <> padtopbottom; cout <> padsides; string::size_type c = 0; // definition of c in the program if (r == padtopbottom + 1 && c == padsides + 1) { // where the error occurs 

Arriba están los bits relevantes del código, el c es del tipo string::size_type porque no sabemos por cuánto tiempo puede estar el saludo, pero ¿por qué tengo este problema ahora, cuando el código del autor no tuvo el problema cuando se usaba? const int ? Además, para cualquiera que haya completado Aceleración de C ++ , ¿se explicará más adelante en este libro?

Estoy en Linux Mint usando g ++ a través de Geany, si eso ayuda o hace una diferencia (como he leído que podría al determinar qué string::size_type es).

Por lo general, es una buena idea declarar variables como unsigned o size_t si se van a comparar con tamaños, para evitar este problema. Siempre que sea posible, use el tipo exacto con el que comparará (por ejemplo, use std::string::size_type al comparar con la longitud de std::string ).

Los comstackdores dan advertencias sobre la comparación de tipos firmados y no firmados porque los intervalos de las notas firmadas y no firmadas son diferentes, y cuando se comparan entre sí, los resultados pueden ser sorprendentes. Si tiene que hacer tal comparación, debe convertir explícitamente uno de los valores a un tipo compatible con el otro, tal vez después de verificar para asegurarse de que la conversión sea válida. Por ejemplo:

 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(); } 

Ayer tuve exactamente el mismo problema al resolver el problema 2-3 en Accelerated C ++. La clave es cambiar todas las variables que va a comparar (usando operadores booleanos) a tipos compatibles. En este caso, eso significa string::size_type (o unsigned int , pero como este ejemplo usa el primero, me quedaré con eso aunque los dos sean técnicamente compatibles).

Tenga en cuenta que en su código original hicieron exactamente esto para el contador c (página 30 en la Sección 2.5 del libro), como lo señaló correctamente.

Lo que hace que este ejemplo sea más complicado es que las diferentes variables de relleno (padsides y padtopbottom), así como también todos los contadores, también se deben cambiar a string::size_type .

Al llegar a tu ejemplo, el código que publicaste terminaría luciendo así:

 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 

Observe que en el condicional anterior, obtendría el error si no inicializara la variable r como una string::size_type en el ciclo for . Entonces, necesita inicializar el bucle for utilizando algo como:

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

Entonces, básicamente, una vez que introduce una variable string::size_type en la mezcla, cada vez que desee realizar una operación booleana en ese elemento, todos los operandos deben tener un tipo compatible para que se compile sin advertencias.

La diferencia importante entre las notas firmadas y no firmadas es la interpretación del último bit. El último bit de los tipos firmados representa el signo del número, es decir, por ejemplo:

0001 es 1 firmado y sin firmar 1001 es -1 firmado y 9 sin firmar

(¡Evité todo el tema del complemento por claridad de explicación! ¡Esta no es exactamente la forma en que se representan las entradas en la memoria!)

Puedes imaginar que hace una diferencia saber si lo comparas con -1 o con +9. En muchos casos, los progtwigdores son demasiado perezosos para declarar contar como no firmados (hinchando la cabeza del bucle for). Por lo general, no es un problema, porque con Ints tienes que contar hasta 2 ^ 31 hasta que tu bit de signo te muerda. Es por eso que es solo una advertencia. Porque somos demasiado perezosos para escribir ‘unsigned’ en lugar de ‘int’.

En los rangos extremos, un int sin signo puede ser más grande que un int.
Por lo tanto, el comstackdor genera una advertencia. Si está seguro de que esto no es un problema, siéntase libre de convertir los tipos al mismo tipo para que desaparezca la advertencia (use el molde C ++ para que sean fáciles de detectar).

Alternativamente, haga que las variables sean del mismo tipo para evitar que el comstackdor se queje.
Quiero decir, ¿es posible tener un relleno negativo? Si es así, guárdelo como int. De lo contrario, probablemente debería utilizar unsigned int y dejar que la transmisión capte las situaciones en las que el usuario ingresa un número negativo.

o use esta biblioteca de encabezado y escriba:

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

y no se preocupan por firmar / firmar o diferentes tamaños