From: Francis Glassborow on
Rune Allnor wrote:
> 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).
>
But reinterpret_cast<> is exactly the case where bit patterns are being
considered along with memory 'footprints'. It is very low level and
intentionally unlikely to be useful in a portable program. Easy
detection was one reason for the long. ugly name (seriously, that was
part of the design of C++ casts)

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

From: Nick Hounsome on
On 24 Nov, 05:51, Rune Allnor <all...(a)tele.ntnu.no> wrote:
> 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

Output format of pointers is not portable and so should never be used
except for debug. (I've seen some horrible implementations that treat
pointers as signed int!!!).

Incidentally you probably should have had setw(2) in your original
hex output because you want 0x01 to come out as 01 not 1.

Also reinterpret_cast is the one new style cast that you really really
want to avoid since it is the least restrictive (The only thing that
the compiler can complain about is trying to use it to remove
constness or volatility)

A char really IS a small integer in both C and C++ and uinsigned int
is definitely at least as big as char so static_cast<unsigned int> is
not in the least bit dodgy. This is why you don't even need a cast to
assign to a temporary variable.

A char really IS NOT a pointer which is why you have to resort to
reinterpret_cast or C style cast to treat it as one.

> http://en.wikipedia.org/wiki/Endianness
>
> means that the internal byte organization is little-endian).
>

Endianness is irrelevant when considering single bytes (char) and
nothing in your output implies little endian anyway.
The only way to see endianness is to take a multibyte integral or
pointer value and treat it as a sequence of bytes:

void* x = ...; // or "int x=..."
char* cp = reinterpret_cast<char*>(&x); // note the &
for(int i=0; i < sizeof(vp); ++i)
cout << setw(2) << hex << static_cast<unsigned int>(*cp);

> Rune


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

From: John H. on
On Nov 23, 4:44 pm, Rune Allnor <all...(a)tele.ntnu.no> wrote:
> 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.
static_cast can be thought of as taking a value of one type and
creating a corresponding value in another type. "Corresponding" can
pretty much mean any relationship, but often means the value of the
created type will be as similar as possible to the value of the source
type.

int num1 = static_cast<long>(3.14);
Here, 3.14 was typecast to a long, which is an integer, so from the
3.14 a 3 is created, which gets stored in num1.

float num2 = static_cast<float>(3);
Here 3 wass typecast to a float, so a 3.0f is created and stored in
num2.

float num3 = static_cast<float>(3.1415926535897932384626433832795);
Here, pi up to many digits of accuracy was converted to a float, which
will have less digits of accuracy

double num4 = static_cast<float>(3.1415926535897932384626433832795);
Here, pi up to many digits of accuracy was converted to a float, which
will have less digits of accuracy. This then gets stored in the
double num4, which could have held more digits of accuracy, but as it
is, those digits were discarded by the cast to float, so when the
float is stored into the double, the extra digits will just be zeros.

reinterpret_cast is different. I am going to say it is usually
applied to pointers and my description will reflect this, but there
may be valid applications to non-pointer types. The reinterpret_cast
takes the bits pointed at by a pointer of some type, and allows those
bit to be accessed as if they were the bits of a variable of a
different type.

Here is an example that shows how the two types of casts behave
differently (details may differ depending on platform):

int num1 = 3; // num1 has a value of 3 and a byte pattern of
0x00000003
float num2 = static_cast<float>(num1); // num2 has a value of 3 and a
byte pattern of 0x40400000
float num3 = *dynamic_cast<float*>(&num1); // num3 has a value of
4.20390e-045 and a byte pattern of 0x00000003

> std::cout << std::hex << c[n] << " ";
I think the std::cout behavior for char and unsigned char is to output
to the ASCII character representation, but for int, long etc. it will
output the numeric representation. So to get the desired behavior, we
have to get to a type that triggers the number rather than character
behavior:
std::cout << std::hex << static_cast<unsigned int>(c[n]) << std::endl;


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