How to output unsigned/signed char or <cstdint> types as integers with << in C++
Background:
I have template stream operators (e.g. operator << (ostream &, std::vector <T>)
) (that output container elements that may possibly be of some 8-bit integer type, (e.g. unsigned char
, int_least8_t
, et cetera).
Problem:
Default is that these types are output as char
(ASCII).
I only used char
(or wchar_t
or whatever) for ASCII variables, never unsigned/signed types.
How do I get these other 8-bit types to always be output as signed int
/ unsigned int
(numbers) instead, even when the caller doesn't know the type?
First tries:
I have tried (with GCC) for example defining operator << (ostream &, unsigned char)
with a cast in it (i.e. stream << static_cast <int> (value)
. That works for unsigned char
values, but then uint8_t
still gets output as a char
.
The same underlying type (i.e. unsigned/signed char
can not be used in overloads, so I can't define an overload of for example operator << (ostream开发者_C百科 &, int_fast8_t)
.
You're confusing the actual data held in a variable, with whatever representation you choose for printing it.
Think of it this way: chars
, ints
, doubles
, longs
, whatevers, they're all just chunks of memory for you to store numbers in. A char is a number between 0 and 255 (or -128 and 127) -- you can choose to represent it as an ASCII character, or as a number, or as stars in the sky with the aid of OpenGL.
If you want to see the number behind the character 'a', just instruct your program to treat that chunk of memory (that for you contains an 'a') as a number. Use casts. Here:
http://www.cplusplus.com/doc/tutorial/typecasting/
See if that helps!
One way that comes to mind is using type traits to define the output type for each type. You would have to declare that for every type by hand. The traits could be defined as a template struct that is specialized for every data-type that has a different output-type than the data-type itself:
template< T >
struct output_trait {
typedef const T & output_type;
}
In your operator you write:
std::cout << static_cast< output_trait< T >::output_type >( variable ) << std::endl;
This will do no cast by default, but for types for which output_trait
is specialized it will do a cast:
template<>
struct output_trait< unsigned char > {
typedef unsigned int output_type;
}
You can simply cast it:
#include<iostream>
int main()
{
uint8_t blah = 65;
std::cout << static_cast<int>(blah) << "\n";
return 0;
}
65
If I have understood you right.. output it like this:
std::cout << ( unsigned int )char << '\n';
Or more c++ style - use static_cast, for example:
int main()
{
char a = 'a';
char b = 97;
std::cout << static_cast< unsigned int >( a ) << '\n';
std::cout << static_cast< unsigned int >( b ) << '\n';
return 0;
}
both std::cout
will print the same: the first one - the ASCII code of 'a'
: 97
, the second one - just the value 97
, stored in b. Both, a
and b
, are absolutely the same.
You can cast them before you output them:
std::cout << (unsigned int) container[index];
精彩评论