0

So I have this so far:

#include <iostream>
#include <string>
#include <typeinfo>

using namespace std;

int main ()
{
    float f = 3.45;           // just an example fp#
    char* ptr = (char*)&f;    // a character pointer to the first byte of the fp#?

    cout << int(ptr[0]) << endl; // these lines are just to see if I get what I 
    cout << int(ptr[1]) << endl; // am looking for... I want ints that I can 
    cout << int(ptr[2]) << endl; // otherwise manipulate.
    cout << int(ptr[3]) << endl;
}
the result is:
-51
-52
92
64

so obviously -51 and -52 are not in the byte range that I would expect for a char... I have taken information from similar questions to arrive at this code and from all discussions, a conversion from char to int is straightforward. So why negative values? I am trying to look at a four-byte number, therefore I would expect 4 integers, each in the range 0-255.

I am using Codeblocks 13.12 with gcc 4.8.1 with option -std=C++11 on a Windows 8.1 device.

EDIT: So the solution was to use:

unsigned char* ptr = reinterpret_cast<unsigned char*>( &f );

Thank you for all the responses.

oweinh
  • 15
  • 5
  • 3
    See http://stackoverflow.com/questions/2054939/is-char-signed-or-unsigned-by-default. – Reto Koradi Jun 08 '14 at 03:09
  • Excellent, thank you @RetoKoradi. I changed the code to unsigned char* ptr ... etc. I had to add -fpermissive to get it to compile, but now the results are 205, 204, 92, 64, which looks good. Thank you again! – oweinh Jun 08 '14 at 03:16
  • @oweinh, Keep in mind `-fpermissive` is not the kind of option you want to leave on. – chris Jun 08 '14 at 03:17
  • @chris is there a way around that? – oweinh Jun 08 '14 at 03:21
  • 1
    It should not be necessary with any special options to make the code compile. Probably you have forgotten to change the pointer variable type, *or* the cast type. – Cheers and hth. - Alf Jun 08 '14 at 03:25
  • Oh, duh. Yeah: unsigned char* ptr = (unsigned char*)&f; – oweinh Jun 08 '14 at 03:27
  • You plan to manipulate the constituent fields of a `float`? Most modern platforms use [IEEE 754](http://en.wikipedia.org/wiki/IEEE_floating_point). I doubt you'll be able to reverse engineer the layout easily without this description. Of course, the question becomes: what are you planning to manipulate the bytes for? – Dietmar Kühl Jun 08 '14 at 03:52
  • I am actually quite good with numeric representations. In my defense, the book I am learning C++ from (Professional C++) does not mention that `char` can be `signed` or `unsigned`. In fact, I am sort of scratching my head wondering what the point of a `signed char` is. "Is that an 'A'? Nope, it's a '-A'" I suppose the point is that you can do math with a `signed` byte, but IMO the default should be `unsigned` and only `signed` if math with byte sized integers is what you are going for. – oweinh Jun 08 '14 at 16:51
  • In C and C++, a char can represent a byte as well as a character. A signed char often represents an integer with values -128..127, an unsigned char an integer with values 0..255. Whether char is signed or unsigned is, AFAIK, implementation dependent. I generally use char for textual tokens like 'A' or 'z', while I use signed or unsigned char for very small integers. – Rudy Velthuis Jun 09 '14 at 14:57
  • Note that on some hardware, bytes are not necessarily octets (8 bit values), and that is why I wrote "often". – Rudy Velthuis Jun 09 '14 at 14:59

1 Answers1

6

Use unsigned char in order to get (guaranteed) unsigned values.

You're getting negative values because with your compiler and compiler options (yes, that matters) char is a signed type.


By the way, the prefix + operator is a handy, concise way to promote a char to int, for the purpose of displaying the numerical value.


Also, by the way, it's a generally good idea to use a C++ named casts (reinterpret_cast, const_cast, static_cast and dynamic_cast) instead of C style casts, where pointers are concerned. That's because a C style cast can end up doing something unexpected, especially when the code is maintained and types changed. In this case you are expressing a reinterpret_cast, so that's the one to use – just for good habit's sake.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
  • Thank you. For some reason a signed character just did not occur to me, but once that was suggested, I was able to fix the code. I have also implemented your suggestion to use the C++ casts rather than C-style. Everything is working as expected now. – oweinh Jun 08 '14 at 03:50