Std :: memcpy or explicit char value assignment - equal and legal value in C ++

In the following example, the representation value is uint32_tcopied to an array uint8_t. This is done using std::memcpy. Since I understand the C ++ standard, this is completely legal: we access an object of type Tthrough T*cast to unsigned char*. There is no problem with an alias, there is no problem with alignment.

The other way is less obvious. We get an object representation Tthrough unsigned char*what is legal. But does access to terms include change?

Of course, there are no aliases and problems with the alias. However, there are problems if the values ​​in the buffer scome from a foreign source: we must ensure the correct orientation and skip the view of the trap. You can check the correct orientation so that it can be solved. But what about traps? How can we avoid this? Or do uint-types have no trap representations, and do not speak double?

I know that another (more compatible?) Way will shift the values uint8_tto the object uint_t. We must still submit to the content, but it should safely drop traps.

But shifts of large types at small μC (8-bit) can be quite expensive!

The next question is: if the second attempt (see below in the code) is equivalent to the approach memcpyregarding legality and functionality? Well, it looks like the version is memcpymore optimized.

#include <cstdint>
#include <cstring>
#include <cassert>

typedef uint32_t utype;

constexpr utype value = 0x01020304;

int main() {
    utype a{value};
    utype b{0};
    uint8_t s[sizeof(utype)]{};

    // first     
    std::memcpy(s, &a, sizeof(utype));
    assert(s[0] == (value & 0xff));

    std::memcpy(&b, s, sizeof(utype));
    assert(b == value);

    // second    

    const uint8_t* ap = reinterpret_cast<const uint8_t*>(&a);
    s[0] = ap[0]; // explicitly legal in C++
    s[1] = ap[1];
    s[2] = ap[2];
    s[3] = ap[3];
    assert(s[0] == (value & 0xff));

    uint8_t* bp = reinterpret_cast<uint8_t*>(&b);
    bp[0] = s[0]; // same as memcpy or ist this UB ?
    bp[1] = s[1];
    bp[2] = s[2];
    bp[3] = s[3];
    assert(b == value);
}
+4
source share
1 answer

But does access to terms include change?

Yes.

Note. In fact, what memcpy does conceptually. It modifies the bytes as if they were narrow character objects. If this is not possible, then memcpy cannot be implemented in standard C ++.

But what about traps? How can we avoid this?

. , , , . , - .

, std::is_trap<T>(void*), .

, ( ?) uint8_t uint_t. , .

, , , , , .

memcpy , endianness, memcpy , .


, uint8_t unsigned char, memcpy. , , , , . .


assert(s[0] == (value & 0xff));

Cpu.

+3

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


All Articles