I'm writing some code that uses the fstream read() function and this function expects a char* as the buffer. Later on, I want to work with the bytes in this buffer as unsigned chars, so I'm either going to have to: 1. declare the buffer as a char* and then do static_casts for each element later, 2. declare the buffer as unsigned char* and then do a reinterpret_cast when I pass it to the read function, or 3. declare the buffer as a char* and also create a casted pointer that I use for accessing the buffer as an unsigned char.
Here's a snippet:
char* buf = new char[512];
unsigned char* ubuf = reinterpret_cast<unsigned char*>(buf);
fstream myfile;
myfile.open("foo.img");
myfile.seekg(446);
myfile.read(buf, 16);
//myfile.read(reinterpret_cast<char*>(buf), 16);
int bytes_per_sector = ubuf[1] << 8 | ubuf[0];
...
I like this way because I only have to cast once and I can just access the buffer as either type without doing a cast every time. But, Is this a good practice? Is there anything that can go wrong here? Using reinterpret_cast makes me a little nervous because I don't normally use it and I've been told to be careful with it so many times.
However, from i=128:255 the chars and the unsigned chars cannot be casted, or you would have different outputs, because unsigned char saves the values from [0:256] and char saves the values in the interval [-128:127]).
unsigned char is a character datatype where the variable consumes all the 8 bits of the memory and there is no sign bit (which is there in signed char). So it means that the range of unsigned char data type ranges from 0 to 255.
When casting character pointer to integer pointer, integer pointer holds some weird value, no where reasonably related to char or char ascii code. But while printing casted variable with '%c', it prints correct char value. Printing with '%d' gives some unknown numbers.
unsigned char ch = (unsigned char)212; printf("%u", (unsigned int)ch); In general, the standard leaves the signedness of char up to the implementation. See this question for more details. Save this answer.
In this case a reinterpret_cast is fine, for 2 reasons:
The (signed) char
and unsigned char
types are required to have the same "representation and alignment". This means that there is not going to be a difference in the data (it will be bit-per bit exact), or how long the buffer is interpreted to be.
File reading functions typically use char*
just as a generic data-access type. They can't use void*
because the type void
has an specifically undefined length and representation. char
, however, does. So they can use it to read/write a series of bytes.
Actually, file-functions are oftentimes intended to have data be reinterpreted as/from something else. It allows you to have a struct like
typedef struct structSomeStruct
{
char name[8]; // a basic, fixed length, string
unsigned long i; // a 32 bit value
float x, y, z, w;
} SomeStruct;
Or
class SomeStruct
{
public:
char name[8];
unsigned long i;
float x, y, z, w;
SomeStruct()
{
// ...
}
};
And store it to a file using something like:
SomeStruct st;
// populate the st data structure
// file.write(char* start_of_data, size_t number_of_bytes);
file.write(reinterpret_cast<char*>(&st), sizeof(SomeStruct));
And read it similarly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With