I am interested in the following question:

struct S { // ... int i; }; void f(uint8_t *_buf, size_t _offset) { uint8_t *pu = _buf + _offset; S *ps = (S*)pu; int *pi = &(ps->i);// UB or not UB? int i; memcpy(&i, pi, sizeof(int)); } 

We have a byte buffer and offset. At the specified offset in the buffer is an object of type S This object has incorrect alignment, like the field i this object.

I am wondering whether it is possible to get the address of the field i described manner, in order to then read the int from the specified address in a safe way, one byte at a time or with the help of memcpy() .

  • It seems that the creation itself (in any way) of a pointer with type int * on an unlined int probably gives UB (by analogy with stackoverflow.com/a/28895321/2752075 ), but I don’t have exact references to the standard. - HolyBlackCat
  • What does "the object has incorrect alignment"? - αλεχολυτ
  • Also, in what language do you write, C or C ++? Or do you need references to the standard in both languages? - HolyBlackCat
  • I write in both languages. - MGNeo

2 answers 2

C99 6.3.2.3/7

It can be converted to a different type of object. If the result is not true, the behavior is undefined . * Otherwise ...

Free translation:

A pointer to an object or an incomplete type can be converted to a pointer to another object or an incomplete type. If the resulting pointer is not aligned correctly for the type to which it will point, the behavior is undefined . Otherwise ...

Those. from the strict words of the C standard, the receipt of any unaligned pointer, regardless of whether it has access to the memory or not - UB.

  • EMNIP on this occasion is not once spears broke ... but I can not find anything like links ... - Fat-Zer
  • I constantly see this code. It turns out that this is a unique UB , and no behavior defined by the implementation should be expected? - MGNeo
  • one
    @MGNeo, I myself am from the camp of those who believed that everything is in order here ... and I, frankly, can hardly imagine the architecture and reasonable implementation for it, where it could give the wrong result (unless some tricky aggressive optimization) ... but you can't argue with Scripture ... - Fat-Zer
  • Did you continue to read the item to which you refer? By the order of the object - αλεχολυτ
  • one
    @MGNeo in your code comment about UB, by the way, it turns out it is necessary to raise it to the drain above. And to get data, create a temporary variable of type S and dump data into it from the buffer. - αλεχολυτ

To do this, it will be enough to take the offset of this field from the beginning of the structure without any intermediate pointers (it is assumed that the structure is the standard layout type):

 ::std::memcpy(::std::addressof(i), _buf + _offset + offsetof(S, i), sizeof(i)); 

As for the attempt to convert a pointer to an object with a less strict alignment to a pointer to an object with a more strict alignment, in C ++ the behavior is not specified (that is, it is specified by the implementation):

8.5.1.10 Reinterpret cast [expr.reinterpret.cast]
7 An object pointer of a different type. 73 When the pointer is static_cast<cv T*>(static_cast<cv void*>(v)) , the result is static_cast<cv T*>(static_cast<cv void*>(v)) . [Note: Conversion of the “ T1 ” to the type “of the pointer to the T2 ” (where T1 and T2 are the types of t1) yields the original pointer value. —End note]

8.5.1.9 Static cast [expr.static.cast]
13 A prvalue of the type “pointer to cv1 void ” can be converted to a prvalue of the type “pointer to cv2 T ”, where is the cv-qualification as, or greater cv-qualification than, cv1 . It is not the case that the original pointer represents the value of the text, and the resulting pointer value is unspecified. Otherwise, if there is a pointer to it, it’s a pointer to interconvertible (6.7.2). Otherwise, the pointer value is unchanged by the conversion.

But to use the received pointer to the structure (even if the implementation correctly performs the address translation) to obtain a pointer to the field of this structure will already be undefined behavior .

  • one
    Comments are not intended for extended discussion; conversation moved to chat . - Yuriy SPb