Pregunta

Considere este programa:

#include <iostream>
#include <string>
#include <sstream>
#include <cassert>

int main()
{
    std::istringstream stream( "-1" );
    unsigned short n = 0;
    stream >> n;
    assert( stream.fail() && n == 0 );
    std::cout << "can't convert -1 to unsigned short" << std::endl;
    return 0;
}

He intentado esto en gcc (versión 4.0.1 de Apple Inc. construir 5490) en OS X 10.5.6 y la afirmación es verdadera; que no puede convertir -1 a un corto sin signo.

En Visual Studio 2005 (y 2008), sin embargo, la afirmación de falla y el valor resultante de n es igual a lo que se puede esperar de un compilador genera la conversión implícita - es decir, "-1" es 65535, "-2" es 65534, etc, pero luego se pone raro al "-32769" que se convierte en 32767.

¿Quién tiene razón y quién está equivocado aquí? (¿Y qué demonios está pasando con -32.769 ??)

¿Fue útil?

Solución

El comportamiento reclamado por GCC en el post de Max Lybbert se basa en los siguientes cuadros MF la Norma C ++ que se asignan comportamiento iostream en convertidores printf / scanf (o al menos eso; 's mi lectura). Sin embargo, el comportamiento scanf de g ++ parece ser diferente del comportamiento istream:

#include <iostream>
#include <cstdio>
using namespace std;;

int main()
{
    unsigned short n = 0;
    if ( ! sscanf( "-1", "%hu", &n ) ) {
        cout << "conversion failed\n";
    }
    else {
        cout << n << endl;
    }
}

En realidad imprime 65.535.

Otros consejos

En primer lugar, la lectura de la cadena "-1" como un número negativo Depende de la localización (sería posible para un entorno local para identificar los números negativos encerrándolas entre paréntesis). Su estándar por defecto es el "clásico" C locale :

  

Con mucho, el uso dominante de lugares es, implícitamente, en la corriente de E / S. Cada istream y ostream tiene su propia local . El local de una corriente es por defecto el mundial local en el momento de la creación de la corriente (página 6). ...

     

En un principio, la configuración regional global es la C local estándar, Locale :: clásica () (página 11).

acuerdo con los chicos del CCG, desbordamiento numérico se permite a fallar la operación de entrada corriente (hablando de cifras negativas que desbordan un signed int):

  

[E] l comportamiento de libstdc ++ - v3 es estrictamente conforme al standard. ... Cuando se intenta realizar la lectura que hace no ajuste en una firmado int i, y falla.

Gracias a otra respuesta, un error fue presentada y este comportamiento cambió :

  

Vaya, al parecer, nunca analiza correctamente los valores negativos para firmar. los   solución es simple. ...

     

fijo en la línea principal, se fija en el punto 4.4.1 también.

Segundo, aunque desbordamiento de entero es generalmente predecible, yo creo que es sin definir oficialmente comportamiento , por lo que si bien no puedo decir por qué -32769" convierte a 32767, creo que está permitido.

Prueba este código:

#include <iostream>
#include <string>
#include <sstream>
#include <cassert>

int main()
{
    std::istringstream stream( "-1" );
    std::cout << "flags: " << (unsigned long)stream.flags() << std::endl;
    return 0;
}

He intentado esto en mi VS2005:

flags: 513

y en codepad.org (que creo que utiliza g ++) esto da:

flags: 4098

Esto me dice que gcc utiliza una fmtflags predeterminado diferente. Dado que el control fmtflags lo que es posible que usted está consiguiendo resultados diferentes. Conversiones

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top