1. why do I need to reinterpret_cast the 1st argument of read() function of ifstream into a char* when reading a file and also casting the 1st argument of write() function of ofstream into a const char*?
The read and write functions work on char values (bytes).
The first argument is a pointer to the first element in a char array where you want to read to/write from.
The second argument is the numbers of char elements that you want to read/write.
By casting a pointer to an object, to char*, you can treat it as a char array and read/write the object char by char (byte by byte).
Unlike other languages (Java, C#, etc.), there is no explicit "byte" data type in C/C++.
So, the char type (and sometimes unsignedchar) has traditionally been used to store "characters" as well as arbitrary byte values. To store a string (sequence of characters) or a byte sequence, a char[] array is used.
Now, when calling the istream::read() or ostream::write() functions, you have to pass a char*pointer, which is pointing to the buffer (i.e. char[] array), where the function will store the bytes that are read from the file, or where the function will take the bytes from that are to be written into the file.
In "modern" C/C++ code, you probably should be using the unit8_t type to store "byte" data. And you will see that many newer libraries that work with "byte" data now use unit8_t* pointers, instead of char* pointers, to pass "byte" sequences. But the istream::read() or ostream::write() functions can not be changed in retrospective, so they are stuck with char* pointers. Therefore, a reinterpret_cast<> cast may be needed!