Reinterpret_cast <> and portabilty

I read that reinterpret_cast<> can be dangerous if it is not used properly. Therefore, I believe that I used it correctly;). I found it useful to use if I have template classes and require type conversion. But recently I read that reinterpret_cast<> also not portable. I am sad about this. What reason? Take the following code,

 void Disp(int* val) { for (int i=0; i < SZ; ++i) { cout << *(val+i) << " "; } cout << endl; } int main() { int arr[SZ]; Disp(arr); unsigned char* ptr = reinterpret_cast<unsigned char*>(arr); for (unsigned char* i = ptr; i < (ptr + (SZ * sizeof(int))); i++) { *i = 0; } Disp(arr); return 0; } 

Now outputs:

 1174214872 32767 4196789 0 568392584 58 4196720 0 0 0 0 0 0 0 0 0 0 0 0 0 Machine type: Linux 2.6.32-358.11.1.el6.x86_64 #1 x86_64 x86_64 x86_64 GNU/Linux 

 975580 -16506540 -13369152 0 -4202936 67876 3 -4202836 4 -4202828 0 0 0 0 0 0 0 0 0 0 Machine type: SunOS DELPHI 5.10 Generic_142900-01 sun4u sparc SUNW,Netra-240 

I copied the outputs of the same program in both Linux and Solaris. I am new to portability issues. So can someone please tell me if I use something like this in my code, it will cause portability problems? Even if not with this code, there is a chance of unexpectedness (undefined behavior) when the code becomes complex (with dynamic allocation and all) and works for long hours. Thanks for the help.

+7
source share
4 answers

The portability problem with reinterpret_cast<> is that different CPUs store numbers differently in memory. Some store them from the least significant byte to the most significant (small end), others do it exactly the opposite (big endian). Some even use some kind of weird byte order, like 1 0 3 2 , don't ask me why.

In any case, the consequence of this is that reinterpret_cast<> carried over unless you rely on the byte order in any way.

Your sample code does not rely on the byte order; it processes all bytes in the same way (setting them to zero), so the code is carried over. If you used reinterpret_cast<> to copy some data object on one computer without interpreting bytes, the code would also be portable ( memcpy() does this).

What is not portable is things, for example, look at the first byte to determine the sign of the number (works only on large computers). If you try to transfer data from one computer to another just by sending the result reinterpret_cast<char*> , you also have problems: the target machine may use a different byte order than the original one, completely interpreting your data incorrectly.

I would say that it is wrong to say that reinterpret_cast<> not portable, it just provides the machine details to the C ++ code, which is machine code. And any code that relies on this machine part is not portable.

+5
source

There are some problems with this code.

  • You display the contents of an uninitialized array. There really is no point.
  • You hardcode the size of your loop, assuming sizeof(int) == 4 . If you are on a machine with a different int size, this will not be portable.
  • If you fill the memory with any value other than zero, you will need to worry about the processor content.

Edit: I see that you edited the hard-coded magic constant 4 , so that point 2 no longer applies.

+5
source

I think that everything is in order. I saw someone claim that it is undefined because the list of allowed aliases in [basic.lval]#10 does not include the use of int values โ€‹โ€‹for aliases written using the char type. (However, on the contrary, this is included).

However, I interpret the "stored value of the object" to still refer to the int value, even after writing via the char alias. This does not seem to be explicitly expressed in the C ++ standard; but in C99 (from which these rules are explicitly derived), it has a different formulation that includes efficient types that indicate that the effective memory type is still int , even though it is written using the char alias.

To clarify; there are other rules in both languages โ€‹โ€‹that cover the question of whether a trap representation has been created. But I saw him claim that the strict alias rule in C ++ is superior to these rules for this case.

0
source

The portability / utility issue of reinterpret_cast<> will be very specific to how it is used. Getting answers to the toy example will not help in any case, when you really may want to use it.

generally speaking, if there is a way to do something without using reinterpret_cast<> , then you need to. Using the example in your question, you can wrap the array to zero without using reinterpret_cast<> using int* (even though I think that your example used of reinterpret_cast <> is in fact well-defined and portable - using a pointer that has been reinterpret-casted to a char * `is one of the few areas that can be portable).

In most cases, when you can find that you need reinterpret_cast<> , you are dealing with something that is really not portable, and you need to understand why you need reinterpret_cast<> in this particular case and understand the portability problems that will be specific to this particular case.

0
source

All Articles