[問題] union 的undefine behavior

看板C_and_CPP作者 (JOMI)時間4年前 (2020/06/16 00:35), 4年前編輯推噓1(1036)
留言37則, 3人參與, 4年前最新討論串1/1
平常真的很少用union 所以當要用的時候還是查了一下 https://en.cppreference.com/w/cpp/language/union S s = {0x12345678}; // initializes the first member, s.n is now the active member // at this point, reading from s.s or s.c is undefined behavior 诶, 這不就是常看到union的標準用法嗎? 於是我再找找 http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Ru-pun 恩....真的是undefined behavior.....完全顛覆我之前對union的認知 原來看到這種union { struct{} , array;} 全部都是UB... 想問一下 1. 即使他是 書本上的UB 但是不是可以說 所有已知compiler實作上都讓他效果一致 也就是常用的那套手段也沒什麼問題, 真的這樣寫 也不用太苛責? 2. 如果真的不想寫出UB 的程式碼, 是不是只能用reinterpret_cast 例如 union Endian{ int a; char b; }; 改用 int a = 1; char b = *(reinterpret_cast<char*>(&a)); 對於reinterpret_cast每當用 都很怕是UB, 有沒有什麼通則可以快速確認是否轉型是UB呢? 以上 (今天才知道union 這樣寫是UB, 實在很震驚) -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 39.12.193.155 (臺灣) ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1592238947.A.863.html ※ 編輯: lovejomi (39.12.193.155 臺灣), 06/16/2020 01:00:08

06/16 02:09, 4年前 , 1F
你的認知應該是從 C 語言來的, 所謂的 active member
06/16 02:09, 1F

06/16 02:09, 4年前 , 2F
就是已經建構好的物件, 如果你要改用另外一個物件就
06/16 02:09, 2F

06/16 02:09, 4年前 , 3F
必須要先解構當前的 active member 再去建構另一個,
06/16 02:09, 3F

06/16 02:09, 4年前 , 4F
在 C++ 裡所有物件都要經過建構才能用, 只有將指標轉
06/16 02:09, 4F

06/16 02:09, 4年前 , 5F
型無視這個規則的都是 UB
06/16 02:09, 5F

06/16 02:12, 4年前 , 6F
對於 non-class object 也是同理, 建構子/解構子一整
06/16 02:12, 6F

06/16 02:12, 4年前 , 7F
套流程缺一不可
06/16 02:12, 7F

06/16 07:34, 4年前 , 8F
如果懶得自己處理就改用 std::variant 吧
06/16 07:34, 8F

06/16 09:49, 4年前 , 9F
可是primitive type要怎麼建構解構(syntax)?
06/16 09:49, 9F

06/16 09:50, 4年前 , 10F
如果要這樣 那之前在C work的union寫法 在C++是不是無法
06/16 09:50, 10F

06/16 09:50, 4年前 , 11F
使用, 如我舉例的Endian 例子...連primitive type也UB?
06/16 09:50, 11F

06/16 09:51, 4年前 , 12F
https://ideone.com/FjHpL0 這樣寫卻沒有建構子被呼叫
06/16 09:51, 12F

06/16 09:51, 4年前 , 13F
合理嗎@@ 這樣我補上解構 不就不對稱了
06/16 09:51, 13F

06/16 10:50, 4年前 , 14F
https://bit.ly/3d22Vlr 參考 [class.union]/6.3 還
06/16 10:50, 14F

06/16 10:50, 4年前 , 15F
06/16 10:50, 15F

06/16 10:51, 4年前 , 16F
[class.union]/7
06/16 10:51, 16F

06/16 11:05, 4年前 , 17F

06/16 11:18, 4年前 , 18F
u.i.~int_t(); 我有私底下這樣寫但實在從來沒看過
06/16 11:18, 18F

06/16 11:18, 4年前 , 19F
但這也證明了 endian那種用法在C++完全是個錯誤?
06/16 11:18, 19F

06/16 11:19, 4年前 , 20F
但也像我第一個問題講的 這種UB真的是無法接受的嗎?
06/16 11:19, 20F

06/16 11:20, 4年前 , 21F
您的例子 透過placement new才會有建構子呼叫
06/16 11:20, 21F

06/16 11:21, 4年前 , 22F
如果一開始就要用 u.s 該怎麼辦呢
06/16 11:21, 22F

06/16 11:24, 4年前 , 23F

06/16 11:25, 4年前 , 24F
是不是 要調整s為第一個 並且 在 {{一定要寫}} ?
06/16 11:25, 24F

06/16 11:26, 4年前 , 25F
UB 是灰色地帶, 只要你確定使用的編譯器行為會如你預
06/16 11:26, 25F

06/16 11:26, 4年前 , 26F
期, 那 UB 就只是可攜性比較差而已. 很多低階的記憶
06/16 11:26, 26F

06/16 11:26, 4年前 , 27F
體操作都是 UB 要靠標準慢慢補完. 可以參考 [P0593]
06/16 11:26, 27F

06/16 11:50, 4年前 , 28F
恩 那 沒跑到建構子是不是也是可接受?
06/16 11:50, 28F

06/16 12:51, 4年前 , 29F
當然不是這樣說 0rz 你沒有跑完 ctor 自然連 dtor 也
06/16 12:51, 29F

06/16 12:52, 4年前 , 30F
不會跑, 尤其是對有 side-effect 的 ctor 來說更是一
06/16 12:52, 30F

06/16 12:52, 4年前 , 31F
定要呼叫
06/16 12:52, 31F

06/16 19:18, 4年前 , 32F
我對side effect這詞用在這領域沒什麼感覺,可否給我一
06/16 19:18, 32F

06/16 19:18, 4年前 , 33F
些延伸資訊呢 謝謝
06/16 19:18, 33F

06/16 20:17, 4年前 , 34F
偶覺得你還是先把基礎打好
06/16 20:17, 34F

06/21 11:02, 4年前 , 35F
想要有保障就用 inheritance,不要用 union 啊
06/21 11:02, 35F

06/21 11:07, 4年前 , 36F
要用 union 就要自己人腦生成 induction principles 和
06/21 11:07, 36F

06/21 11:07, 4年前 , 37F
檢查所有 introduction/elimination
06/21 11:07, 37F
文章代碼(AID): #1UvwDZXZ (C_and_CPP)