-1

Let's assume that A and B are two classes (or structures) having no inheritance relationships (thus, object slicing cannot work). I also have an object b of the type B. I would like to interpret its binary value as a value of type A:

A a = b;

I could use reinterpret_cast, but I would need to use pointers:

A a = reinterpret_cast<A>(b);       // error: invalid cast
A a = *reinterpret_cast<A *>(&b);   // correct [EDIT: see *footnote]

Is there a more compact way (without pointers) that does the same? (Including the case where sizeof(A) != sizeof(B))

Example of code that works using pointers: [EDIT: see *footnote]

#include <iostream>
using namespace std;

struct C {
    int i;
    string s;
};

struct S {
    unsigned char data[sizeof(C)];
};

int main() {
    C c;
    c.i = 4;
    c.s = "this is a string";

    S s = *reinterpret_cast<S *>(&c);
    C s1 = *reinterpret_cast<C *>(&s);

    cout << s1.i << " " << s1.s << endl;
    cout << reinterpret_cast<C *>(&s)->i << endl;

    return 0;
}

*footnote: It worked when I tried it, but it is actually an undefined behavior (which means that it may work or not) - see comments below

Codoscope
  • 892
  • 1
  • 10
  • 18
  • 3
    Why do you want to do this? –  Jun 17 '17 at 12:48
  • 4
    Your basic premise leads directly to Undefined Behaviour. Your example is also UB - casting and dereferencing pointers of unrelated types. The standard does allow casts to char * and std::memcpy to move regions of storage - but the destination need to be the same type as the origin to avoid UB. – Richard Critten Jun 17 '17 at 12:48
  • 2
    What is the purpose of the cast? Why do you want to do it? What is the actual problem such a cast is supposed to solve? Please take some time to read about [the XY problem](http://xyproblem.info/). – Some programmer dude Jun 17 '17 at 12:52
  • I don't understand why my question would deserve -1. It is not about the purpose, which would be too long to detail here. @RichardCritten: My code perfectly works, if you want to try it: http://www.tutorialspoint.com/compile_cpp_online.php?PID=0Bw_CjBb95KQMVXZvVXBReFNEeUU – Codoscope Jun 17 '17 at 12:56
  • 1
    *Undefined behavior* is very well allowed to *"work perfectly"* on your specific platform - but that doesn't mean much as it could do something completely else when compiled on a different platform. Also to answer your actual question - no, there is no shorter way of doing this (except maybe using C-style casts instead of `reinterpret_cast` but it does the same thing) – UnholySheep Jun 17 '17 at 13:01
  • @UnholySheep: Why would it be an undefined behavior? Please explain what can go wrong in the code that I gave. – Codoscope Jun 17 '17 at 13:04
  • @RichardCritten Already has... "Your example is also UB - casting and dereferencing pointers of unrelated types. The standard does allow casts to char * and std::memcpy to move regions of storage - but the destination need to be the same type as the origin to avoid UB." – George Jun 17 '17 at 13:06
  • 1
    [*Undefined behavior*](http://en.cppreference.com/w/cpp/language/ub) is part of the C++ language specification - if you read the reference page it clearly states: *"[...] **access to an object through a pointer of a different type**, etc. Compilers are not required to diagnose undefined behavior (although many simple situations are diagnosed), and the **compiled program is not required to do anything meaningful**."* – UnholySheep Jun 17 '17 at 13:07
  • Ok, I understand, although it is strange since the dereferenced value of the wrong type is not used. So is there a way to do so without undefined behavior? (And I still don't understand why -1, after all the efforts I made for this question, it's very frustrating) – Codoscope Jun 17 '17 at 13:15
  • 1
    Have +1, the questions was well asked. However, you said _".. since the dereferenced value of the wrong type is not used ..."_. It gets used here: `S s = *reinterpret_cast(&c);` Please also read the following to see why UB should be avoided especially when combined with modern compiler optimisations: http://en.cppreference.com/w/cpp/language/ub – Richard Critten Jun 17 '17 at 13:22
  • @RichardCritten: Thank you! Yes, what I meant by not used was that I don't use its fields. -- To give more insight about what I want to do, I would like to give generically a value to a part of the program that knows its real type, without using pointers like `void *`. – Codoscope Jun 17 '17 at 13:33
  • Templates or inheritance hierarchy (common base class). You probably need to open a new question with your real problem. Also _"...I don't use its fields.."_ that expression is assignment, what do you think it does to the fields of the class on the left-hand-side and the fields on the right? Assignment does not just blindly copy the bits of an object. – Richard Critten Jun 17 '17 at 13:34
  • Ok, I see, but the thing is that what I am looking for is precisely that it copy the bits (or not even copy them but just interpret them with a different type). – Codoscope Jun 17 '17 at 13:41
  • _" just interpret them with a different type"_ : You can't the standard defines that as UB. – Richard Critten Jun 17 '17 at 14:05
  • You could use a `union` containing a `C` and an `S` to make this slightly more portable, but still technically Undefined Behavior. – aschepler Jun 17 '17 at 14:19
  • If you need to "copy" the object across some barrier, consider serialization. https://stackoverflow.com/questions/447898/what-is-object-serialization You can't just memcpy things and expect it to work. For example, this code will fail when you try to look at the string. That's exactly WHY it is undefined in the spec. Also useful, look at https://stackoverflow.com/questions/146452/what-are-pod-types-in-c If you can ensure that you have pod types, just memcpy will work for serialization, but ... please do use void* (and size) or a std container, so people can tell what's going on. – Kenny Ostrom Jun 17 '17 at 14:20

2 Answers2

1

No. I think there's nothing in the C++ syntax that allows you to implicitly ignore types. First, that's against the notion of static typing. Second, C++ lacks standardization at binary level. So, whatever you do to trick the compiler about the types you're using might be specific to a compiler implementation.

That being said, if you really wanna do it, you should check how your compiler's data alignment/padding works (i.e.: struct padding in c++) and if there's a way to control it (i.e.: What is the meaning of "__attribute__((packed, aligned(4))) "). If you're planning to do this across compilers (i.e.: with data transmitted across the network), then you should be extra careful. There are also platform issues, like different addressing models and endianness.

Pedro Boechat
  • 2,446
  • 1
  • 20
  • 25
-1

Yes, you can do it without a pointer:

A a = reinterpret_cast<A &>(b);       // note the '&'

Note that this may be undefined behaviour. Check out the exact conditions at http://en.cppreference.com/w/cpp/language/reinterpret_cast

geza
  • 28,403
  • 6
  • 61
  • 135
  • Eh. The standard says this is equivalent to `A a = *reinterpret_cast(&b)`, so this isn't really "without a pointer". – Cody Gray - on strike Jun 17 '17 at 14:50
  • Is UB. Read(6) and _Type Aliasing Rules_. http://en.cppreference.com/w/cpp/language/reinterpret_cast – Richard Critten Jun 17 '17 at 14:51
  • Yes, it is UB, but the question wasn't about its UBness (the pointer way is UB too). Qu'est-ce t'y ont asked whether it can be done without a pointer, and a more compact way (it is almost as many characters as the pointer way, though). – geza Jun 17 '17 at 14:57
  • If it is UB how _"... can be done..."_ be achieved? UB by definition means that the result of the operation is undefined so no result can be predicted or relied upon. – Richard Critten Jun 17 '17 at 15:29
  • His/her solutions is already UB, my solution doesn't make it worse. To me it seems that he/she didn't know that & can be placed at the first reinterpret_cast, and it will compile. Besides, if he/she checks that the compiled code does exactly what he/she wants, then everything could be fine. There was no mention that a non-UB solution is needed. But I understand your point too, of course, and you're right that this kind of solutions must be avoided, if possible. – geza Jun 17 '17 at 15:56
  • +1 because it does provide a more compact solution, but I think that you should still include in your answer that it is actually an undefined behavior (just as I added to my question). – Codoscope Jun 17 '17 at 17:52