bit_cast 除了 memcpy 之外还有什么额外的 UB?
What, if any, additional UB will bit_cast have beyond memcpy?
我有一个 class,其目的是将可能具有对齐限制的数据移入或移出数据未对齐的序列化内存缓冲区。我已按如下方式设置和获取处理程序:
#include <cstring>
template<typename T>
struct handle_type {
static inline T get(const void *data) {
T value;
memcpy(&value, data, sizeof(T));
return value;
}
static inline void set(void *data, T value) {
memcpy(data, &value, sizeof(T));
}
};
c++20出来后,我希望它能变成这样:
#include <bit>
template<typename T>
struct handle_type {
union unaligned { char bytes[sizeof(T)]; }; // EDIT: changed from struct
static inline T get(const void *data) {
return std::bit_cast<T>(*(const unaligned*)data);
}
static inline void set(void *data, T value) {
*(unaligned *)data = std::bit_cast<unaligned>(value);
}
};
有用吗?还是我使用的是 inerim 类型,未对齐的结构类型,容易造成问题?
除非用户提供了指向 unaligned
对象的指针,否则您的 get
函数是 UB。您的 set
函数与 UB 类似,除非 data
是一个 unaligned
对象。这两种情况都违反了严格的别名。请记住:严格的别名后门是关于实际的 char*
;这与碰巧 包含 一个 char*
.
的对象不同
此外,set
可能是一个编译错误,完全取决于 unaligned
的实现是否与 T
具有相同的大小。毕竟,unaligned
最后可能有填充。
bit_cast
想主要处理对象,而不是内存的随机缓冲区。为此,你应该坚持 memcpy
.
<changed to use union
instead of struct
>
这没有任何改变;使用 union
并不能保证 union
的大小等于其最大数据成员的大小。来自 [class.union]/2:
The size of a union is sufficient to contain the largest of its non-static data members.
添加了强调:"sufficient",而不是 "equal to"。该标准允许实现使联合大于其最大数据成员的能力,因为这样的大小仍然是 "sufficient".
我有一个 class,其目的是将可能具有对齐限制的数据移入或移出数据未对齐的序列化内存缓冲区。我已按如下方式设置和获取处理程序:
#include <cstring>
template<typename T>
struct handle_type {
static inline T get(const void *data) {
T value;
memcpy(&value, data, sizeof(T));
return value;
}
static inline void set(void *data, T value) {
memcpy(data, &value, sizeof(T));
}
};
c++20出来后,我希望它能变成这样:
#include <bit>
template<typename T>
struct handle_type {
union unaligned { char bytes[sizeof(T)]; }; // EDIT: changed from struct
static inline T get(const void *data) {
return std::bit_cast<T>(*(const unaligned*)data);
}
static inline void set(void *data, T value) {
*(unaligned *)data = std::bit_cast<unaligned>(value);
}
};
有用吗?还是我使用的是 inerim 类型,未对齐的结构类型,容易造成问题?
除非用户提供了指向 unaligned
对象的指针,否则您的 get
函数是 UB。您的 set
函数与 UB 类似,除非 data
是一个 unaligned
对象。这两种情况都违反了严格的别名。请记住:严格的别名后门是关于实际的 char*
;这与碰巧 包含 一个 char*
.
此外,set
可能是一个编译错误,完全取决于 unaligned
的实现是否与 T
具有相同的大小。毕竟,unaligned
最后可能有填充。
bit_cast
想主要处理对象,而不是内存的随机缓冲区。为此,你应该坚持 memcpy
.
<changed to use
union
instead ofstruct
>
这没有任何改变;使用 union
并不能保证 union
的大小等于其最大数据成员的大小。来自 [class.union]/2:
The size of a union is sufficient to contain the largest of its non-static data members.
添加了强调:"sufficient",而不是 "equal to"。该标准允许实现使联合大于其最大数据成员的能力,因为这样的大小仍然是 "sufficient".