so another casting question, in the below code I have a function addNumbers which returns the sum of the two arguments,
I cast the double* ( address of the doubles I want as arguments) to int*, when I do this , the value that is printed is pretty much garbage, it prints a large arbitrary number, what I thought would happen is that 59.3 would be truncated to 59 and 88.9 would be truncated to 88, but that isn't the case
could it be to do with the fact that a double is 8 bytes and an int is 4? but when casting a normal double to a normal int the value is just truncated, how come this isn't the case here?
If you just want to truncate a double to an integer you just say:
1 2
double d = 1.23;
int n = (int)d;
But you are casting addresses, not values. In doing so you are reinterpreting the underlying bytes. The layout of a floating point value and the layout of an integer are totally different (in particular, a floating point value stores 2 different integers and a separate sign bit). It's pretty much meaningless to print out int-sized chunks of a double. Printing char-sized chunks (bytes) is potentially interesting, allowing you to see the underlying format of the value.
1 2 3 4 5 6 7 8 9 10
#include <iostream>
#include <iomanip>
int main() {
double d = 1.23;
auto p = (unsignedchar*)&d;
std::cout << std::hex << std::setfill('0');
for (int i = 0; i < 8; ++i)
std::cout << std::setw(2) << (unsigned)(*p++) << '\n';
}
I am trying to experiment around with casting pointer types to different pointer types but my compiler is stopping me from doing so, even a reinterpret cast will not work, from what I have seen some C compilers allow you to do this, how come my compiler is stopping me from doing so? and is there a way around this?
I am using a 32 bit mingw compiler
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
int a = 150;
int* p_a = &a;
double b = 12.3;
double* p_b = &b;
char c = 'a';
char* p_c = &c;
p_b = (int*)p_b; // does not work : cannot convert 'int*' to 'double*' in assignment
p_b = reinterpret_cast<int*>(p_b); // also does not work : cannot convert 'int*'
// to'double*' in assignment
Look closely. I think you mean to assign the (int*) to p_a, not p_b. If you actually want to assign it to p_b then I have to ask what you think that would do? It would basically be meaningless.
how come here in this sense it is ok to convert an int pointer to a character(byte) pointer?
I'm not sure I understand. Why not? You can convert any pointer to a byte pointer.
The read function is a low-level input function that works byte-by-byte. You need to pass it a byte pointer (char*) to the first position of the memory you want to fill and a count of the number of bytes you want to read into that memory. It just reads bytes and stuffs them into memory, any bytes, any memory.
We can write the 32-bit integer normally and then read it in second half-first:
#include <iostream>
#include <iomanip>
#include <fstream>
#include <cstdint> // for definite-sized types
int main() {
constchar* const Filename = "binary.bin";
uint32_t n = 0x01020304;
std::cout << std::hex << std::setfill('0');
std::cout << std::setw(8) << n << '\n'; // 01020304
// When opening for in|out mode, it fails if the file doesn't exist
std::fstream bin(Filename, bin.binary | bin.in | bin.out);
if (!bin) {
bin.clear();
// So we create the file in out mode, close it, and try to open it again.
bin.open(Filename, bin.binary | bin.out);
if (!bin) {
std::cerr << "Cannot open file.\n";
return 1;
}
bin.close();
bin.open(Filename, bin.binary | bin.in | bin.out); // assuming success (!)
}
auto p = (char*)&n;
bin.write(p, sizeof n); // write the 4 bytes starting at address p to the file
bin.seekg(0); // reset file position to the beginning
n = 0; // so we can tell if the reads failed
// read first half into second half and second half into first.
bin.read(p+2, sizeof n / 2); // read 2 bytes from the file into bytes starting at p+2
bin.read(p, sizeof n / 2); // read the next 2 bytes into bytes starting at p
std::cout << std::setw(8) << n << '\n'; // 03040102
}
// read first half into second half and second half into first.
bin.read(p+2, sizeof n / 2); // read 2 bytes from the file into bytes starting at p+2
bin.read(p, sizeof n / 2); // read the next 2 bytes into bytes starting at p
std::cout << std::setw(8) << n << '\n'; // 03040102
wow that is actually pretty neat :o, that is quite powerful,
is there any times where apart from reading and writing binary data that you would need to do an reinterpret cast? have you ever used it in a project?
Those pointer casts are all reinterpret_casts. Reinterpreting the underlying bytes of an object is potentially dangerous, mostly non-portable, and often avoidable. The basic evil of reinterpret_cast is that it totally sidesteps the type system, which is the heart and soul of C++. In a properly-structured C++ project, such casting would only exist at the lowest levels if at all.
In the previous code, we were using c-style casts which are frowned upon in C++ since they don't distinguish between radically different kinds of cast.
Real-life use cases can emerge at the interface between systems to handle hardware differences, such as swapping the endianness of a value (reversing the order of its bytes), although the bytes can also be moved around with shifts, etc. So there is often another option.