From: Rune Allnor on
Hi all.

I need to inspect the bit patterns in a buffer. In order to do that, I
want
to print the values of each character to screen as numerical values
on
hex format.

Below is an example program that shows a number of more or less
successful attempts to achieve this. The buffer c is initialized with
the
hexadecimal numbers 0x30, 0x31, 0x32 and 0x33, which happens
to be the ASCII values of the characters '0', '1', '2' and '3'.

In attempt a) I just pipe the ASCII values to std::cout along with a
hint that I want the hex values to be printed. The attempt is clearly
unsuccessful, as the characters, not the hex values, are printed.

In attempt b) I type cast the values of the buffer from uchar to
uint. This has the desired effect, at the expense of using a
C-style type cast, which is something I want to avoid, if at all
possible.

Attempt c), where I achieve the desired result by assigning the
uchar value to be printed to the temporary uint variable d is a bit
clumsy, since it involves a temporary variable that is not strictly
necessary, either from a semantic or algorithmic point of view.

So the question is if it is possible to achieve the desired result
by using a reinterpret_cast<> or static_cast<> directly on the uchar
values inside the buffer c?

I can't see any obvious way to achieve this, since chars
have a different memory footprint than any of the int types
I am aware of, that otherwise would suit the purpose.

Are there any data types with the same memory footprint as
chars, that are interpreted by the IO library as numeric integer
values, as opposed to text glyphs?

Rune

--------------- Output ----------------
a) Naive output:
0 1 2 3

b) C-style type cast:
30 31 32 33

c) Type cast by variable assignment:
30 31 32 33
---------------------------------------

/////////////////////////////////////////////////////////////////////////////
#include <iomanip>
#include <iostream>

int main()
{
// Hex values of digits: 0 1 2 3
unsigned char c[] = {0x30,0x31,0x32,0x33};
std::cout << "a) Naive output:" << std::endl;
for (size_t n = 0; n != 4; ++n)
{
std::cout << std::hex << c[n] << " ";
}
std::cout << std::endl << std::endl;

std::cout << "b) C-style type cast:" << std::endl;
for (size_t n = 0; n != 4; ++n)
{
std::cout << std::hex << (unsigned int) c[n] << " ";
}
std::cout << std::endl << std::endl;

std::cout << "c) Type cast by variable assignment:" << std::endl;
for (size_t n = 0; n != 4; ++n)
{
size_t d = c[n];
std::cout << std::hex << d << " ";
}
std::cout << std::endl;
return 0;
}

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Neil Butterworth on
Rune Allnor wrote:
> Hi all.
>
> I need to inspect the bit patterns in a buffer. In order to do that, I
> want
> to print the values of each character to screen as numerical values
> on
> hex format.
>
> Below is an example program that shows a number of more or less
> successful attempts to achieve this. The buffer c is initialized with
> the
> hexadecimal numbers 0x30, 0x31, 0x32 and 0x33, which happens
> to be the ASCII values of the characters '0', '1', '2' and '3'.
>
> In attempt a) I just pipe the ASCII values to std::cout along with a
> hint that I want the hex values to be printed. The attempt is clearly
> unsuccessful, as the characters, not the hex values, are printed.
>
> In attempt b) I type cast the values of the buffer from uchar to
> uint. This has the desired effect, at the expense of using a
> C-style type cast, which is something I want to avoid, if at all
> possible.
>
> Attempt c), where I achieve the desired result by assigning the
> uchar value to be printed to the temporary uint variable d is a bit
> clumsy, since it involves a temporary variable that is not strictly
> necessary, either from a semantic or algorithmic point of view.
>
> So the question is if it is possible to achieve the desired result
> by using a reinterpret_cast<> or static_cast<> directly on the uchar
> values inside the buffer c?
>
> I can't see any obvious way to achieve this, since chars
> have a different memory footprint than any of the int types
> I am aware of, that otherwise would suit the purpose.
>
> Are there any data types with the same memory footprint as
> chars, that are interpreted by the IO library as numeric integer
> values, as opposed to text glyphs?
>
> Rune
>
> --------------- Output ----------------
> a) Naive output:
> 0 1 2 3
>
> b) C-style type cast:
> 30 31 32 33
>
> c) Type cast by variable assignment:
> 30 31 32 33
> ---------------------------------------
>
> /////////////////////////////////////////////////////////////////////////////
> #include <iomanip>
> #include <iostream>
>
> int main()
> {
> // Hex values of digits: 0 1 2 3
> unsigned char c[] = {0x30,0x31,0x32,0x33};
> std::cout << "a) Naive output:" << std::endl;
> for (size_t n = 0; n != 4; ++n)
> {
> std::cout << std::hex << c[n] << " ";
> }
> std::cout << std::endl << std::endl;
>
> std::cout << "b) C-style type cast:" << std::endl;
> for (size_t n = 0; n != 4; ++n)
> {
> std::cout << std::hex << (unsigned int) c[n] << " ";
> }
> std::cout << std::endl << std::endl;
>
> std::cout << "c) Type cast by variable assignment:" << std::endl;
> for (size_t n = 0; n != 4; ++n)
> {
> size_t d = c[n];
> std::cout << std::hex << d << " ";
> }
> std::cout << std::endl;
> return 0;
> }

I can't see what is wrong with the obvious:

std::cout << std::hex << static_cast<unsigned int>(c[n]) << " ";

And I don't see why you think having a "different memory footprint"
precludes a cast - a cast creates a new value which may have a
completely different "footprint" from the thing the cast is applied to.

Neil Butterworth

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Daniel Krügler on
On 23 Nov., 22:44, Rune Allnor <all...(a)tele.ntnu.no> wrote:
> Hi all.
>
> I need to inspect the bit patterns in a buffer. In order to do that, I
> want
> to print the values of each character to screen as numerical values
> on
> hex format.
>
> Below is an example program that shows a number of more or less
> successful attempts to achieve this. The buffer c is initialized with
> the
> hexadecimal numbers 0x30, 0x31, 0x32 and 0x33, which happens
> to be the ASCII values of the characters '0', '1', '2' and '3'.
>
> In attempt a) I just pipe the ASCII values to std::cout along with a
> hint that I want the hex values to be printed. The attempt is clearly
> unsuccessful, as the characters, not the hex values, are printed.

Yes, this is intended behavior.

> In attempt b) I type cast the values of the buffer from uchar to
> uint. This has the desired effect, at the expense of using a
> C-style type cast, which is something I want to avoid, if at all
> possible.

So, why not using a static_cast then?

> Attempt c), where I achieve the desired result by assigning the
> uchar value to be printed to the temporary uint variable d is a bit
> clumsy, since it involves a temporary variable that is not strictly
> necessary, either from a semantic or algorithmic point of view.
>
> So the question is if it is possible to achieve the desired result
> by using a reinterpret_cast<> or static_cast<> directly on the uchar
> values inside the buffer c?

No. What is your hesitation about a static_cast? You could
also simply rely on implicit conversion with a very tiny helper
function:

inline int to_int(char c) { return c; }

You could also easily define your own IO manipulator, which
performs this for you and would perform the to-hex conversion
in one step:

struct char_as_hex_t {
int c;
char_as_hex_t(char c) : c(c) {}
};

inline char_as_hex_t as_hex(char c) {
return char_as_hex_t(c);
}

template <typename Ch, typename Tr>
inline std::basic_ostream<Ch, Tr>& operator<<(
std::basic_ostream<Ch, Tr>& os,
char_as_hex_t manip)
{
os << std::hex << manip.c;
return os;
}

and use it like this:

std::cout << as_hex('a') << std::endl;

If you are really cool, you define char_as_hex_t
as a template, which is specialized for all integral
types with special handling for the character types.
In this case I would rename it to "as_hex" or so.

> I can't see any obvious way to achieve this, since chars
> have a different memory footprint than any of the int types
> I am aware of, that otherwise would suit the purpose.
>
> Are there any data types with the same memory footprint as
> chars, that are interpreted by the IO library as numeric integer
> values, as opposed to text glyphs?

This depends on which sizeof ratios the fundamental types
have ;-)
On some machines you may find sizeof(char) == sizeof(long double).
IMO your search for "same memory footprint" in this kind of
example is premature optimization of the worst kind: For most
machines an int function argument is much more advantageous
than a (1-octet) char, because the registers need to be
unpacked again, while int typically has already the proper
register size. You could use unsigned short, but I would
never do this in this example - just stay with int.

HTH & Greetings from Bremen,

Daniel Kr�gler


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Francis Glassborow on
Rune Allnor wrote:
> Hi all.
>
> I need to inspect the bit patterns in a buffer. In order to do that, I
> want
> to print the values of each character to screen as numerical values
> on
> hex format.
>
> Below is an example program that shows a number of more or less
> successful attempts to achieve this. The buffer c is initialized with
> the
> hexadecimal numbers 0x30, 0x31, 0x32 and 0x33, which happens
> to be the ASCII values of the characters '0', '1', '2' and '3'.
>
> In attempt a) I just pipe the ASCII values to std::cout along with a
> hint that I want the hex values to be printed. The attempt is clearly
> unsuccessful, as the characters, not the hex values, are printed.
>
> In attempt b) I type cast the values of the buffer from uchar to
> uint. This has the desired effect, at the expense of using a
> C-style type cast, which is something I want to avoid, if at all
> possible.
>
> Attempt c), where I achieve the desired result by assigning the
> uchar value to be printed to the temporary uint variable d is a bit
> clumsy, since it involves a temporary variable that is not strictly
> necessary, either from a semantic or algorithmic point of view.
>
> So the question is if it is possible to achieve the desired result
> by using a reinterpret_cast<> or static_cast<> directly on the uchar
> values inside the buffer c?
>
> I can't see any obvious way to achieve this, since chars
> have a different memory footprint than any of the int types
> I am aware of, that otherwise would suit the purpose.
>
> Are there any data types with the same memory footprint as
> chars, that are interpreted by the IO library as numeric integer
> values, as opposed to text glyphs?
What has memory footprint got to do with static_cast<> ?

int main() {
// Hex values of digits: 0 1 2 3
unsigned char c[] = {0x30,0x31,0x32,0x33};
std::cout << "Using static_cast<> " << std::endl;
for (size_t n = 0; n != 4; ++n) {
std::cout << std::hex << static_cast<unsigned int> (c[n])
<< " ";
}
std::cout << std::endl << std::endl;

return 0;
}

Note that casts are generally about values not about storage types. In
C++ problems can arise if you cast to a reference type but that is not
the case here.

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Rune Allnor on
Hm.

Wrote the code and the post in parallel, so I lost the
point first time around.

In the code below is the test using reinterpret_cast<>
added, along with the corresponding added output.
As can be seen, each char value is preceeded by a number
of leading zeros that I am unable to get rid of. I assume
this has something to do with memory footprints and/or byte
ordering (I am using VS2008 on a PC, which, according to

http://en.wikipedia.org/wiki/Endianness

means that the internal byte organization is little-endian).

Rune

> --------------- Output ----------------
> a) Naive output:
> 0 1 2 3
>
> b) C-style type cast:
> 30 31 32 33
>
> c) Type cast by variable assignment:
> 30 31 32 33

d) reinterpret_cast:
00000030 00000031 00000032 00000033

> ---------------------------------------
>
> ///////////////////////////////////////////////////////////////////////////�//
> #include <iomanip>
> #include <iostream>
>
> int main()
> {
> // Hex values of digits: 0 1 2 3
> unsigned char c[] = {0x30,0x31,0x32,0x33};
> std::cout << "a) Naive output:" << std::endl;
> for (size_t n = 0; n != 4; ++n)
> {
> std::cout << std::hex << c[n] << " ";
> }
> std::cout << std::endl << std::endl;
>
> std::cout << "b) C-style type cast:" << std::endl;
> for (size_t n = 0; n != 4; ++n)
> {
> std::cout << std::hex << (unsigned int) c[n] << " ";
> }
> std::cout << std::endl << std::endl;
>
> std::cout << "c) Type cast by variable assignment:" << std::endl;
> for (size_t n = 0; n != 4; ++n)
> {
> size_t d = c[n];
> std::cout << std::hex << d << " ";
> }
> std::cout << std::endl;

///////////////////////////////////////////////////
std::cout << "d) reinterpret_cast:"
<< std::endl;
for (size_t n = 0; n != 4; ++n)
{
std::cout << std::hex << reinterpret_cast<int*> (c[n]) << " ";
}
std::cout << std::endl << std::endl;
///////////////////////////////////////////////////
> return 0;
>
> }


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]