[英]Strict aliasing and union of char arrays
我有點期望答案會是什么,但很好奇標准對此有何評論。
設置:我想控制結構中字段的確切偏移量,並直接在字段類型中指定它們。 這是魔術:
#include <type_traits>
#include <cstdint>
#include <cstring>
#include <new>
template <uint32_t OFFSET, typename T>
struct FieldOverlay
{
static_assert(std::is_trivial<T>::value, "Can only be used with trivial types");
FieldOverlay() = delete;
FieldOverlay(FieldOverlay&& other) = delete;
FieldOverlay(FieldOverlay const& other) = delete;
FieldOverlay& operator = (T const& val) { new (buf + OFFSET) T(val); return *this; }
operator T()
{
T v;
::memcpy(&v, buf + OFFSET, sizeof(T));
return v;
}
private:
char buf[OFFSET + sizeof(T)];
};
// Precisely control member offsets
union MyMessage
{
FieldOverlay<0, uint32_t> x;
FieldOverlay<7, uint32_t> y;
};
void exampleUsage(MyMessage& m)
{
m.y = m.x;
}
struct MyMessageEquivalent
{
uint32_t x;
char padding[3];
uint32_t y;
} __attribute__ ((packed));
這將在帶有-O3 -std=c++1z -fstrict-aliasing -Wall -Wpedantic -Wextra -Werror
gcc 6.3上進行編譯,並且沒有任何錯誤,並且可以正常工作。 (參見Godbolt: https ://godbolt.org/g/DHWLD9)
問題:這是否符合標准? 我認為這很容易,因為工會MyMessage
沒有一個“活動”成員。 但是,由於所有內容都是通過char
數組訪問的,因此對嚴格混疊規則有幫助嗎?
您的代碼有很多的問題,但你會調用UB 很久以前嚴格走樣甚至是一個問題。
MyMessage::x
和MyMessage::y
不是布局兼容類型。 它們也沒有共同的初始序列。 是的,盡管它們都存儲一個char
數組,但它們沒有存儲相同大小的char
數組。 這兩個數組的長度不同,並且通用的初始序列規則中沒有任何內容表明包含兩個具有相同基本類型但大小不同的兩個數組的結構具有相同的初始序列。
因此,當y
是聯合的活動成員時,您將無法嘗試訪問x
。 反之亦然。
僅供參考:您對演員表的重新解釋也會引起UB。 該內存中沒有T
,並且reinterpret_cast
無法創建對象。 因此,訪問該內存就好像包含一個T
違反了標准。 另外,該標准不允許您通過未對齊的指針訪問對象。
因此,基本上,您想要做的將永遠不會起作用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.