简体   繁体   中英

Difference between static_cast<char*> and (char*)

this is my first question :)

I have one pile file, and I have open it like shown below ;

ifstream in ( filename,  ios :: binary | ios :: in ) 

Then, I wish hold 2 byte data in unsigned int hold ;

unsigned int hold;
in . read(static_cast<char *>(&hold), 2); 

It seems correct to me. However, when I compile it with

g++  -ansi -pedantic-errors -Werror - -Wall  -o main main.cpp 

Compiler emits error

error: invalid static_cast from type ‘unsigned int*’ to type ‘char*’ 

Actually, I have solved this problem by changing static_cast with ( char*), that is

unsigned int hold;
in . read((char*)(&hold), 2); 

My questions are :

  • What is the difference(s) between static_cast<char*> and (char*) ?
  • I am not sure whether using (char*) is a safer or not. If you have enough knowledge, can you inform me about that topic ?

NOTE : If you have better idea, please help me so that I can improve my question?

static_cast is a safer cast than the implicit C style cast. If you try to cast an entity which is not compatible to another, then static_cast gives you an compilation time error unlike the implicit c-style cast.

static_cast gives you an error here because what you are trying to say is take an int and try to fit it in a char , which is not possible. int needs more memory than what char occupies and the conversion cannot be done in a safe manner.

If you still want to acheive this,You can use reinterpret_cast , It allows you to typecast two completely different data types, but it is not safe.
The only guarantee you get with reinterpret_cast is that if you cast the result back to the original type, you will get the same value, But no other safety guarantees.

  • first - you can easily search for _cast and find any c++ cast. Searching c-style casts is a lot harder.
  • second - if you use c++ casts, you need to choose the correct one. In your case, it is reinterpret_cast .
    The c-style cast does everything.

you can also check here: http://www.cplusplus.com/doc/tutorial/typecasting/ for the differences of the different c++ casts. I strongly recommend only to use c++ casts. This way you can easily find & check them later and you are forced to think about what you are actually doing there. This improves code quality!

You should have used reinterpret_cast<char *> instead of static_cast<char *> , because the data types are not related: you can convert between a pointer to a subclass to a superclass for instance, or between int and long , or between void * and any pointer, but unsigned int * to char * isn't "safe" and thus you cannot do it with static_cast .

The difference is that in C++ you have various types of casts:

  • static_cast which is for "safe" conversions;

  • reinterpret_cast which is for "unsafe" conversions;

  • const_cast which is for removing a const attribute;

  • dynamic_cast which is for downcasting (casting a pointer/reference from a superclass to a subclass).

The C-style cast (char *)x can mean all of these above, so it is not as clear as the C++ casts. Furthermore, it is easy to grep for a C++-style cast (just grep for _cast ), but it's quite hard to search for all C-style casts.

The static_cast is illegal here; you're casting between unrelated pointer types. The solution to get it to compile would be to use reinterpret_cast (which is what (char*) resolves to in this case). Which, of course, tells you that the code isn't portable, and in fact, unless you're doing some very low level work, probably won't work correctly in all cases.

In this case, of course, you're reading raw data, and claiming it's an unsigned int . Which it isn't; what read inputs is raw data, which you still have to manually convert to whatever you need, according to the format used when writing the file. (There is no such thing as unformatted data. Just data with an undocumented, unspecified, or unknown format. The “unformatted” input and output in iostream are designed to read and write char buffers which you format manually. The need for reinterpret_cast here is a definite warning that something is wrong with your code. (There are exceptions, of course, but they're few and far between.)

You will typically get these errors during binary file I/O using ifstream or ofstream or fstream. Problem is that these streams have methods that take const char* while what you have is array of some other type. You want to write your array as binary bits in to the file.

The traditional way of doing this is using old-style cast (char*) which basically just says that whatever pointer I've treat it as (char*) . The old style casts are discouraged by pedantic/strict mode . To get rid of those warnings, the C++11 equivalent is reinterpret_cast<const char*> .

I would say, if you are doing binary file I/O then you already know things may or may not be portable depending on how you save the file in one OS and read in another OS. That's whole another issue, however, don't get scared by reinterpret_cast<const char*> because that's what you have to do if you want to write bytes to file.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM