I have a weird problem about working with integers in C++.
I wrote a simple program that sets a value to a variable and then prints it, but it is not working as expe
cout
is treating aa
as char
of ASCII value 5
which is an unprintable character, try typecasting to int
before printing.
As others said before the problem occurs because standard stream treats signed char and unsigned char as single characters and not as numbers.
Here is my solution with minimal code changes:
uint8_t aa = 5;
cout << "value is " << aa + 0 << endl;
Adding "+0"
is safe with any number including floating point.
For integer types it will change type of result to int
if sizeof(aa) < sizeof(int)
. And it will not change type if sizeof(aa) >= sizeof(int)
.
This solution is also good for preparing int8_t
to be printed to stream while some other solutions are not so good:
int8_t aa = -120;
cout << "value is " << aa + 0 << endl;
cout << "bad value is " << unsigned(aa) << endl;
Output:
value is -120
bad value is 4294967176
P.S. Solution with ADL given by pepper_chico and πάντα ῥεῖ is really beautiful.
uint8_t
will most likely be a typedef
for unsigned char
. The ostream
class has a special overload for unsigned char
, i.e. it prints the character with the number 5, which is non-printable, hence the empty space.
Adding a unary + operator before the variable of any primitive data type will give printable numerical value instead of ASCII character(in case of char type).
uint8_t aa = 5;
cout<<"value is "<< +aa <<endl; // value is 5
It's because the output operator treats the uint8_t
like a char
(uint8_t
is usually just an alias for unsigned char
), so it prints the character with the ASCII code (which is the most common character encoding system) 5
.
See e.g. this reference.
Making use of ADL (Argument-dependent name lookup):
#include <cstdint>
#include <iostream>
#include <typeinfo>
namespace numerical_chars {
inline std::ostream &operator<<(std::ostream &os, char c) {
return std::is_signed<char>::value ? os << static_cast<int>(c)
: os << static_cast<unsigned int>(c);
}
inline std::ostream &operator<<(std::ostream &os, signed char c) {
return os << static_cast<int>(c);
}
inline std::ostream &operator<<(std::ostream &os, unsigned char c) {
return os << static_cast<unsigned int>(c);
}
}
int main() {
using namespace std;
uint8_t i = 42;
{
cout << i << endl;
}
{
using namespace numerical_chars;
cout << i << endl;
}
}
output:
*
42
A custom stream manipulator would also be possible.
cout << +i << endl
).