最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c++ - Need for an intermediate struct in a type punning example with `std::bit_cast` - Stack Overflow

programmeradmin6浏览0评论

I was reading this excellent material about the strict aliasing rule: or

But in the section about std::bit_cast and an alleged limitation of std::bit_cast, I don't understand the need for both a std::memcpy and a std::bit_cast.

The provided example seemed a bit contrived and can be simplified to:

#include <bit>
#include <cstring>

struct some_chars {
    unsigned char arr[sizeof(unsigned int)] = {};
};
unsigned int foo(unsigned char *p) {
    some_chars a;
    std::memcpy(a.arr, p, sizeof(unsigned int));
    unsigned int result = std::bit_cast<unsigned int>(a);
    return result;
}

(see here)
(Here and in the following, p is assumed to point to a storage of at least sizeof(unsigned int) unsigned char)

I'm finding the purpose of the intermediate struct unclear. What would be wrong with the following?

unsigned int foo(unsigned char *p) {
    unsigned int result;
    std::memcpy(&result, p, sizeof(unsigned int));
    return result;
}

why not std::memcpy directly into an unsigned int as illustrated in cpprefence?

// reinterpreting
double d = 0.1;
//  std::int64_t n = *reinterpret_cast<std::int64_t*>(&d); // aliasing violation
std::int64_t n;
std::memcpy(&n, &d, sizeof d); // OK

LIVE

I was reading this excellent material about the strict aliasing rule: https://stackoverflow/a/51228315/21691539 or https://gist.github/shafik/a956a17d00024b32b35634eeba1eb49e

But in the section about std::bit_cast and an alleged limitation of std::bit_cast, I don't understand the need for both a std::memcpy and a std::bit_cast.

The provided example seemed a bit contrived and can be simplified to:

#include <bit>
#include <cstring>

struct some_chars {
    unsigned char arr[sizeof(unsigned int)] = {};
};
unsigned int foo(unsigned char *p) {
    some_chars a;
    std::memcpy(a.arr, p, sizeof(unsigned int));
    unsigned int result = std::bit_cast<unsigned int>(a);
    return result;
}

(see here)
(Here and in the following, p is assumed to point to a storage of at least sizeof(unsigned int) unsigned char)

I'm finding the purpose of the intermediate struct unclear. What would be wrong with the following?

unsigned int foo(unsigned char *p) {
    unsigned int result;
    std::memcpy(&result, p, sizeof(unsigned int));
    return result;
}

why not std::memcpy directly into an unsigned int as illustrated in cpprefence?

// reinterpreting
double d = 0.1;
//  std::int64_t n = *reinterpret_cast<std::int64_t*>(&d); // aliasing violation
std::int64_t n;
std::memcpy(&n, &d, sizeof d); // OK

LIVE

Share Improve this question asked 1 hour ago OerstedOersted 2,6446 silver badges26 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 1

bit_cast is for converting the object representation of one type to another type. But bit_cast requires having a live object of the source type. And the source type must be a value type.

p is a pointer to some bytes. And while p itself is a value type, which it points to isn't. bit_cast needs a value type, so you have to copy the desired bytes into a value type and then perform the cast.

What would be wrong with the following?

memcpying into a live object is only permitted to work by the standard if the source bits came from a live object of that type, as described in [basic.types]/2&3. So if p pointed to data that is an object representation of an unsigned int created by a copy from a valid unsigned int, then it does work. But if p pointed to, say, various bits you loaded from a file or got from the internet or wherever, then as far as the standard is concerned, all bets are off.

bit_cast is less restrictive; as long as the bits represent a valid value of the new type, bit_cast will manifest that value in the returned object type.

发布评论

评论列表(0)

  1. 暂无评论