Is the structure of one element compatible with the element itself?

If I have the following structure:

struct Foo { int a; }; 

Below is the code that complies with the C ++ standard? I mean, can't it generate "Undefined Behavior"?

 Foo foo; int ifoo; foo = *reinterpret_cast<Foo*>(&ifoo); void bar(int value); bar(*reinterpret_cast<int*>(&foo)); auto fptr = static_cast<void(*)(...)>(&bar); fptr(foo); 
+6
source share
3 answers

9.2 / 20 in the N3290 says

A pointer to a standard layout structure object properly converted using reinterpret_cast points to its initial member (or if this element is a bit field, and then to the unit in which it is located) and vice versa.

And your Foo is the standard layout class.

So, your second actor is correct.

I don’t see a guarantee that the first one is correct (and I used an architecture where char had less alignment restriction than a structure containing only char on such an architecture, that would be problematic). The standard guarantee is that if you have a pointer to an int that really points to the first element of the structure, you can re-integrate it back to the pointer to the structure.

Likewise, I don’t see anything that your third definite could do if it were reinterpret_cast (I am sure that some ABIs use a different convention to pass structures and base types, so it is very suspicious and I will need a clear mention in standard to accept it), and I'm sure nothing allows static_cast between function pointers.

+10
source

As long as you gain access only to the first element of the structure, it is considered safe, since there is no spacer in front of the first element of the structure. In fact, this trick is used, for example, in the Objecive-C runtime, where the generic pointer type is defined as:

 typedef struct objc_object { Class isa; } *id; 

and at runtime, real objects (which still remain hidden pointers to a structure) have memory layouts like this:

 struct { Class isa; int x; // random other data as instance variables } *CustomObject; 

and the runtime accesses the class of the real object using this method.

+4
source

Foo is a structure with plain old data, which means that it only contains data that you explicitly store in it. In this case: int. Thus, the memory layout for int and Foo is the same.

You can automatically output from one to another without problems. Whether it is a smart idea to use this material is another question.

PS: This one usually works, but not necessarily due to different alignment restrictions. See AProgrammer's answer.

+2
source

Source: https://habr.com/ru/post/906652/


All Articles