Click here to Skip to main content
15,888,802 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
According to the type aliasing rules i assume that:

1) direct conversion of uint64_t* to uint32_t* - is incorrect

2) conversion chains is OK
uint64_t* -> unsigned char* -> uint32_t*
uint64_t* -> void* -> uint32_t*

Am i understanding the rules correctly or not?

I'm always prefer to use unions instead, to prevent any possible ptr. conversion problems (which can cause data corruption), but it is not always possible (and good) solution.

What I have tried:

Type aliasing rules: reinterpret_cast conversion - cppreference.com[^]
Posted
Updated 13-Jun-16 8:48am
v2

First of all, you need to understand what this type of cast does: it reinteprets the object taking all data of a source object bit by bit. Second thing to understand is: all pointer objects are of the same size.

You can always convert between all pointers, and the cast itself will always work, but the validity of this operation depends on what you are going to do with the area of memory pointed by the pointer. In general case, it can give you access to some area behind the object pointed to be the original pointer. The result of such access can be different. In some cases, you can get just garbage. In other cases, you may access the object behind the memory area reserved for the original object, so you can write to this area (note that your pointers are not constant), corrupt those objects, cause General Protection Fault exception, anything.

Note all of those kind of trouble can happen even without the cast, if, by some other reason, your pointer points to some wrong area of memory.

Let's see:

  1. uint64_t* to uint32_t*
    No problem, except loosing part of data for 64-bit integers which are bigger than maximum 32-bit integers, so you can get wrong data. (With negative data, the situation is the same, just more complicated; please see Two's complement — Wikipedia, the free encyclopedia.)
    You cannot harm other data, because the new pointer, result of the case, gives you access to smaller area of memory than.
  2. uint64_t* -> unsigned char* -> uint32_t*
    uint64_t* -> void* -> uint32_t*


    It depends what you are doing. If you don't touch intermediate pointer objects (unsigned char*, void*), just cast it again, it makes no difference. This intermediate cast is simply redundant, makes no sense at all. You cannot access anything directly with void pointer unless you cast it again. As to pointer to a character, it points to even less area of memory than pointer to uint32, so you cannot corrupt anything using it, by the reason I explained in item #1.

Note that I never mentioned the purpose of all these manipulations, so I'm an not sure anything of that makes no sense. The question about "correctness" of these operations does not make any predefined sense; it all depends on what you try to achieve and what you are going to do with the results of the case. The most important thing is that you have to understand what really happens.

—SA
 
Share this answer
 
v3
Comments
Shvetsov Evgeniy 16-Jun-16 8:20am    
Ok, looks like i didn't formed the question correctly (precisely enough), living too much room for condsierations. But this is my own fault, while your answer is detailed, interesting and usefull, i would accept it. Thank you.
Sergey Alexandrovich Kryukov 16-Jun-16 9:26am    
Thank you, Evgeny.
—SA
Assuming you actually mean uint64_t and uint32_t, it makes no real difference. The real issue is how your code will handle the numeric values correctly. You need to understand that casting does not convert anything. All it does is tell the compiler, "I am doing something slightly dangerous here, but I know what I am doing".
 
Share this answer
 
Comments
Shvetsov Evgeniy 16-Jun-16 8:21am    
Thanks for your reply! Yes, to handle the resulted values correctly is the problem.
Richard MacCutchan 16-Jun-16 10:53am    
Which is why I added the final sentence. If you have an array of uint_64 values, and you use a uint_32* to access it, then you will (possibly) get strange results. ArrayItem[0] will be the low order part of the first 64-bit value, ArrayItem[1] will be the high order part, and so on. If that is what you want then that's OK, but maybe that is not what you want.
Shvetsov Evgeniy 17-Jun-16 10:06am    
"ArrayItem[0] will be the low order part of the first 64-bit value, ArrayItem[1] will be the high order part" - on little-endian machines, i guess. The problem is, as i now know it, reading values using uint32_t* pointer, converted from original uint64_t* pointer - is undefined behaivour, due to the CPP standart. So it can be just garbage or this code can evenly be optimized out by the compiler. I hope it is NOT, as i'm using such a code already, but can't be sure, espically for other platforms. I really love C++ but some thimes i just hate it. And i blame myself for stupidity too.
Richard MacCutchan 17-Jun-16 11:26am    
Exactly so, which is why I wrote what I did. The main point as I mentioned in my first answer "it tells the compiler, "I am doing something slightly dangerous here, but I know what I am doing".. But you really do need to understand the underlying structure of the data you are trying to access.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900