uint8_t no se puede imprimir con cout

Tengo un problema extraño sobre trabajar con enteros en C ++.

Escribí un progtwig simple que establece un valor para una variable y luego la imprime, pero no está funcionando como se esperaba.

Mi progtwig tiene solo dos líneas de código:

uint8_t aa = 5; cout << "value is " << aa << endl; 

El resultado de este progtwig es el value is

Es decir, imprime en blanco para aa .

Cuando cambio uint8_t por uint16_t el código anterior funciona como un amuleto.

Uso Ubuntu 12.04 (Precise Pangolin), de 64 bits, y mi versión del comstackdor es:

 gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5) 

Realmente no imprime un espacio en blanco, pero muy probablemente el carácter ASCII con valor 5, que no es imprimible (o invisible). Hay una serie de códigos invisibles de caracteres ASCII , la mayoría de ellos por debajo del valor 32, que es el espacio en blanco en realidad.

ostream& operator< <(ostream&, unsigned char) convertir aa en unsigned int para generar el valor numérico, ya que ostream& operator< <(ostream&, unsigned char) intenta generar el valor del carácter visible.

 uint8_t aa=5; cout < < "value is " << unsigned(aa) << endl; 

uint8_t probablemente será un typedef para unsigned char . La clase ostream tiene una sobrecarga especial para unsigned char , es decir, imprime el carácter con el número 5, que no es imprimible, de ahí el espacio vacío.

Agregar un operador unario + antes de la variable de cualquier tipo de datos primitivos dará valor numérico imprimible en lugar de caracteres ASCII (en el caso del tipo de caracteres).

 uint8_t aa=5; cout< <"value is "<< +aa < 
  • Haciendo uso de ADL (búsqueda de nombre dependiente del argumento):

     #include  #include  #include  namespace numerical_chars { inline std::ostream &operator< <(std::ostream &os, char c) { return std::is_signed::value ? os < < static_cast(c) : os < < static_cast(c); } inline std::ostream &operator< <(std::ostream &os, signed char c) { return os << static_cast(c); } inline std::ostream &operator< <(std::ostream &os, unsigned char c) { return os << static_cast(c); } } int main() { using namespace std; uint8_t i = 42; { cout < < i << endl; } { using namespace numerical_chars; cout << i << endl; } } 

    salida:

     * 42 
  • Un manipulador de flujo personalizado también sería posible.

  • El operador unario plus también es una expresión clara ( cout < < +i << endl ).

Se debe a que el operador de salida trata el uint8_t como un char ( uint8_t suele ser solo un alias para unsigned char ), por lo que imprime el carácter con el código ASCII (que es el sistema de encoding de caracteres más común) 5 .

Ver, por ejemplo, esta referencia .

cout está tratando aa como char de ASCII valor 5 que es un carácter no imprimible, intente encasillar a int antes de imprimir.

La sobrecarga del operator< <() entre istream y char es una función no miembro. Puede usar explícitamente la función de miembro para tratar un char (o un uint8_t ) como int .

 #include  #include  int main() { uint8_t aa=5; std::cout < < "value is "; std::cout.operator<<(aa); std::cout << std::endl; return 0; } 

Salida:

 value is 5 

Como otros dijeron antes, el problema ocurre porque la transmisión estándar trata a los caracteres con signo y sin signo como caracteres únicos y no como números.

Aquí está mi solución con cambios mínimos de código:

 uint8_t aa = 5; cout < < "value is " << aa + 0 << endl; 

Agregar "+0" es seguro con cualquier número, incluido el punto flotante.

Para tipos enteros, cambiará el tipo de resultado a int si sizeof(aa) < sizeof(int) . Y no cambiará de tipo si sizeof(aa) >= sizeof(int) .

Esta solución también es buena para preparar int8_t para que se imprima en streaming, mientras que otras soluciones no son tan buenas:

 int8_t aa = -120; cout < < "value is " << aa + 0 << endl; cout << "bad value is " << unsigned(aa) << endl; 

Salida:

 value is -120 bad value is 4294967176 

La solución PS con ADL dada por pepper_chico y πάντα ῥεῖ es realmente hermosa.