type geeksforgeeks data bool and c++ type-conversion sizeof unsigned modular

c++ - geeksforgeeks - ¿Por qué es-1> sizeof(int)?



types of numbers c++ (4)

Considera el siguiente código:

template<bool> class StaticAssert; template<> class StaticAssert<true> {}; StaticAssert< (-1 < sizeof(int)) > xyz1; // Compile error StaticAssert< (-1 > sizeof(int)) > xyz2; // OK

¿Por qué es -1 > sizeof(int) cierto?

  1. Es cierto que -1 se promueve a unsigned(-1) y luego a unsigned(-1) > sizeof(int) .
  2. ¿Es cierto que -1 > sizeof(int) es equivalente a -1 > size_t(4) si sizeof (int) es 4. Si es así, ¿por qué -1 > size_t(4) es falso?

¿Es este el estándar de C ++?


porque -1 se convierte a size_t y este es un tipo de datos sin signo, por lo que (size_t)-1 == 4294967295 (en un sistema de 32 bits) que es definitivamente mayor que 4

si agrega -Wall a la configuración de gcc, por ejemplo, recibirá una advertencia de que está comparando un tipo de datos firmado y otro sin firmar


A continuación se muestra cómo el estándar (ISO 14882) explica abort-1> sizeof (int)

El operador relacional `> ''se define en 5.9 (expr.rel / 2)

Las conversiones aritméticas habituales se realizan en operandos de tipo aritmético o de enumeración. ...

Las conversiones aritméticas usuales se definen en 5 (expr / 9)

... El patrón se denomina conversiones aritméticas habituales, que se definen de la siguiente manera:

  • Si cualquiera de los operandos es de tipo double long, ...
  • De lo contrario, si alguno de los operandos es dobule, ...
  • De lo contrario, si alguno de los operandos es flotante, ...
  • De lo contrario, las promociones integrales se realizarán en ambos operandos.
  • ...

Las promociones integrales se definen en 4.5 (conv.prom / 1)

Un rvalue de tipo char, signed char, unsigned char, short int o unsigned short int se puede convertir a un rvalue de tipo int si int puede representar todos los valores del tipo de fuente; de lo contrario, el valor de origen r se puede convertir a un valor r de tipo unsigned int.

El resultado de sizeof se define en 5.3.3 (expr.sizeof / 6)

El resultado es una constante de tipo size_t

size_t se define en el estándar C (ISO 9899), que es un tipo de entero sin signo .

Entonces, para -1 > sizeof(int) , el> desencadena conversiones aritméticas habituales. La conversión aritmética habitual convierte -1 en unsigned int porque int no puede representar todo el valor de size_t . -1 convierte en un número muy grande que depende de la plataforma. Entonces -1 > sizeof(int) es true .


Debido a que unsigned es más fuerte que firmó y -1 se convirtió al valor sin signo a partir de size_t , por lo que en realidad -1 == 0xFFFFFFFF > 4

Así es como debería funcionar según el estándar C ++


Es simple y triste. En C / C ++:

  1. la mayoría de las veces, los tipos enteros sin signo tienen la semántica de enteros modulares (representan clases de equivalencia)
  2. las comparaciones de tipos enteros sin signo tienen la semántica del orden entero habitual, de modo que 1U < 2U (IOW 0U es el valor más pequeño unsigned )
  3. sizeof tiene tipo size_t
  4. size_t es un tipo de entero sin signo
  5. El punto (1) implica que los cálculos aritméticos mixtos que involucran un entero con signo y sin signo se realizan en aritmética modular sin signo: esta es la única posibilidad sin violar la regla "medio sin signo sin signo". Es trivial convertir un entero a la clase de equivalencia de enteros equivalentes a él. (Mientras que ir hacia otro lado requiere la elección de un número entero para representar la clase de equivalencia).
  6. El punto (5) implica que -1 < 1U se interpreta como unsigned(-1) < 1U , y unsigned(-1) = - 1U , y obviamente - 1U < 1U , por lo que -1 < 1U es verdadero.
  7. Los puntos (1,3,4) implican que el sizeof something actúa (principalmente) como una clase equivalente (!!!).
  8. Todo esto implica que -1 < sizeof something

La conclusión: este es un error de diseño heredado de C.

Regla:

Utilice únicamente tipos sin signo para aritmética modular, manipulaciones de bits ( & , | , ^ , << , >> , ~ operadores), manipulaciones de bytes ( unsigned char significa "byte" en C / C ++) y caracteres (carácter unsigned char significa carácter en C / C ++).

No use tipos sin signo para hacer aritmética.

Si una función espera un valor entero que nunca debería ser negativo, tome un número entero con signo y, opcionalmente, verifique en la función que el valor está dentro del rango.