Saya telah menggunakan serikat pekerja sebelumnya dengan nyaman; hari ini saya terkejut ketika saya membaca posting ini dan mengetahui kode ini
union ARGB
{
uint32_t colour;
struct componentsTag
{
uint8_t b;
uint8_t g;
uint8_t r;
uint8_t a;
} components;
} pixel;
pixel.colour = 0xff040201; // ARGB::colour is the active member from now on
// somewhere down the line, without any edit to pixel
if(pixel.components.a) // accessing the non-active member ARGB::components
sebenarnya adalah perilaku yang tidak terdefinisi. Yaitu membaca dari anggota serikat selain yang baru-baru ini ditulis untuk mengarah pada perilaku yang tidak terdefinisi. Jika ini bukan tujuan penggunaan serikat, lalu apa? Bisakah seseorang menjelaskannya dengan terperinci?
Memperbarui:
Saya ingin mengklarifikasi beberapa hal di belakang.
- Jawaban untuk pertanyaan tidak sama untuk C dan C ++; diri saya yang lebih muda dan bodoh menandainya sebagai C dan C ++.
- Setelah menjelajahi melalui standar C ++ 11, saya tidak dapat secara meyakinkan mengatakan bahwa itu memanggil mengakses / memeriksa anggota serikat yang tidak aktif tidak ditentukan / tidak ditentukan / implementasi-didefinisikan. Yang bisa saya temukan adalah §9.5 / 1:
Jika penyatuan tata letak standar berisi beberapa struct tata letak standar yang berbagi urutan awal yang sama, dan jika objek tipe penyatuan tata letak standar ini berisi salah satu struktur tata letak standar, maka diizinkan untuk memeriksa urutan awal umum dari setiap anggota struct tata letak standar. §9.2 / 19: Dua struct tata letak standar berbagi urutan awal yang sama jika anggota yang sesuai memiliki tipe yang kompatibel dengan tata letak dan tidak ada anggota yang merupakan bidang bit atau keduanya adalah bidang bit dengan lebar yang sama untuk urutan satu atau lebih inisial anggota
- Sementara di C, ( C99 TC3 - DR 283 dan seterusnya) adalah sah untuk melakukannya ( terima kasih kepada Pascal Cuoq untuk membawa ini). Namun, upaya untuk melakukannya masih dapat menyebabkan perilaku tidak terdefinisi , jika nilai yang dibaca tidak valid (disebut "representasi perangkap") untuk jenis yang akan dibaca. Jika tidak, nilai yang dibaca adalah implementasi yang ditentukan.
C89 / 90 menyebutkan hal ini berdasarkan perilaku yang tidak ditentukan (Lampiran J) dan buku K&R mengatakan bahwa implementasinya didefinisikan. Kutipan dari K&R:
Ini adalah tujuan dari persatuan - variabel tunggal yang dapat secara sah menampung salah satu dari beberapa jenis. [...] selama penggunaannya konsisten: jenis yang diambil harus jenis yang paling baru disimpan. Merupakan tanggung jawab programmer untuk melacak jenis apa yang saat ini disimpan dalam serikat pekerja; hasilnya tergantung pada implementasi jika sesuatu disimpan sebagai satu jenis dan diekstraksi sebagai yang lain.
Ekstrak dari Stroustrup's TC ++ PL (tambang penekanan)
Penggunaan serikat pekerja dapat menjadi sangat penting untuk kesesuaian data [...] terkadang disalahgunakan untuk "konversi tipe ".
Di atas segalanya, pertanyaan ini (yang judulnya tetap tidak berubah sejak permintaan saya) diajukan dengan maksud untuk memahami tujuan serikat pekerja DAN tidak pada standar yang memungkinkan. Misalnya, menggunakan pewarisan untuk penggunaan kembali kode, tentu saja, diizinkan oleh standar C ++, tetapi itu bukan tujuan atau niat awal untuk memperkenalkan warisan sebagai fitur bahasa C ++ . Inilah alasan mengapa jawaban Andrey tetap seperti yang diterima.
scouring C++11's standard I couldn't conclusively say that it calls out accessing/inspecting a non-active union member is undefined [...] All I could find was §9.5/1
...Betulkah? Anda mengutip catatan pengecualian , bukan poin utama tepat di awal paragraf : "Dalam sebuah serikat, paling banyak salah satu anggota data non-statis dapat aktif kapan saja, yaitu nilai paling banyak dari satu anggota data non-statis dapat disimpan dalam serikat kapan saja. " - dan turun ke p4: "Secara umum, seseorang harus menggunakan panggilan destruktor eksplisit dan penempatan operator baru untuk mengubah anggota aktif serikat "
b, g, r,
dana
mungkin tidak berdekatan, dan dengan demikian tidak cocok dengan tata letak auint32_t
. Ini merupakan tambahan untuk masalah Endianess yang telah ditunjukkan oleh orang lain.