Dengan penyatuan, Anda hanya boleh menggunakan salah satu elemen, karena semuanya disimpan di tempat yang sama. Ini berguna ketika Anda ingin menyimpan sesuatu yang bisa menjadi salah satu dari beberapa jenis. Sebuah struct, di sisi lain, memiliki lokasi memori yang terpisah untuk masing-masing elemennya dan semuanya dapat digunakan sekaligus.
Untuk memberikan contoh konkret tentang penggunaannya, saya sedang mengerjakan juru bahasa Skema beberapa waktu yang lalu dan pada dasarnya saya overlay tipe data Skema ke tipe data C. Ini melibatkan penyimpanan dalam sebuah enum struktural yang menunjukkan jenis nilai dan gabungan untuk menyimpan nilai itu.
union foo {
int a; // can't use both a and b at once
char b;
} foo;
struct bar {
int a; // can use both a and b simultaneously
char b;
} bar;
union foo x;
x.a = 3; // OK
x.b = 'c'; // NO! this affects the value of x.a!
struct bar y;
y.a = 3; // OK
y.b = 'c'; // OK
sunting: Jika Anda bertanya-tanya pengaturan xb ke 'c' apa yang mengubah nilai xa menjadi, secara teknis itu tidak terdefinisi. Pada kebanyakan mesin modern, char adalah 1 byte dan int adalah 4 byte, sehingga memberikan xb nilai 'c' juga memberikan byte pertama xa dengan nilai yang sama:
union foo x;
x.a = 3;
x.b = 'c';
printf("%i, %i\n", x.a, x.b);
cetakan
99, 99
Mengapa kedua nilainya sama? Karena 3 byte terakhir dari int 3 semuanya nol, jadi itu juga dibaca sebagai 99. Jika kita memasukkan angka yang lebih besar untuk xa, Anda akan melihat bahwa ini tidak selalu terjadi:
union foo x;
x.a = 387439;
x.b = 'c';
printf("%i, %i\n", x.a, x.b);
cetakan
387427, 99
Untuk melihat lebih dekat nilai-nilai memori aktual, mari kita atur dan cetak nilai-nilai dalam hex:
union foo x;
x.a = 0xDEADBEEF;
x.b = 0x22;
printf("%x, %x\n", x.a, x.b);
cetakan
deadbe22, 22
Anda dapat dengan jelas melihat di mana 0x22 menimpa 0xEF.
TAPI
Di C, urutan byte dalam int tidak ditentukan.Program ini menimpa 0xEF dengan 0x22 pada Mac saya, tetapi ada platform lain di mana ia akan menimpa 0xDE sebagai gantinya karena urutan byte yang membentuk int dibatalkan. Oleh karena itu, ketika menulis sebuah program, Anda tidak boleh mengandalkan perilaku menimpa data tertentu dalam serikat karena itu tidak portabel.
Untuk membaca lebih lanjut tentang urutan byte, lihat endianness .
Inilah jawaban singkatnya: sebuah struct adalah struktur rekaman: setiap elemen dalam struct mengalokasikan ruang baru. Jadi, struct suka
mengalokasikan setidaknya
(sizeof(int)+sizeof(long)+sizeof(double)+sizeof(long double))
byte dalam memori untuk setiap instance. ("Setidaknya" karena kendala penyelarasan arsitektur dapat memaksa kompiler untuk memasang struct.)Di samping itu,
mengalokasikan satu keping memori dan memberinya empat alias. Jadi
sizeof(union foobarbazquux_u) ≥ max((sizeof(int),sizeof(long),sizeof(double),sizeof(long double))
, sekali lagi dengan kemungkinan beberapa penambahan untuk keberpihakan.sumber
Protokol komunikasi imajiner
Dalam protokol imajiner ini, telah ditentukan bahwa, berdasarkan "tipe pesan", lokasi berikut di header akan berupa nomor permintaan, atau kode empat karakter, tetapi tidak keduanya. Singkatnya, serikat pekerja memungkinkan lokasi penyimpanan yang sama untuk mewakili lebih dari satu tipe data, di mana dijamin Anda hanya ingin menyimpan salah satu jenis data pada satu waktu.
Serikat pekerja sebagian besar detail tingkat rendah yang berbasis pada warisan C sebagai bahasa pemrograman sistem, di mana lokasi penyimpanan "tumpang tindih" kadang-kadang digunakan dengan cara ini. Kadang-kadang Anda dapat menggunakan serikat pekerja untuk menghemat memori tempat Anda memiliki struktur data tempat hanya satu dari beberapa jenis yang akan disimpan sekaligus.
Secara umum, OS tidak peduli atau tahu tentang struct dan serikat - keduanya hanya blok memori untuk itu. Str adalah blok memori yang menyimpan beberapa objek data, di mana objek tersebut tidak tumpang tindih. Serikat adalah blok memori yang menyimpan beberapa objek data, tetapi hanya memiliki penyimpanan untuk yang terbesar dari ini, dan dengan demikian hanya dapat menyimpan salah satu objek data pada satu waktu.
sumber
packetheader ph;
bagaimana Anda mengakses nomor permintaan?ph.request.requestnumber
?Seperti yang sudah Anda nyatakan dalam pertanyaan Anda, perbedaan utama di antara
union
danstruct
adalah bahwaunion
anggota saling overlay memori sehingga ukuran serikat adalah satu, sementarastruct
anggota diletakkan satu demi satu (dengan bantalan opsional di antaranya). Serikat pekerja juga cukup besar untuk menampung semua anggotanya, dan memiliki keberpihakan yang cocok dengan semua anggotanya. Jadi katakanlahint
hanya dapat disimpan pada alamat 2 byte dan lebar 2 byte, dan panjang hanya dapat disimpan pada alamat 4 byte dan panjangnya adalah 4 byte. Persatuan berikutdapat memiliki
sizeof
4, dan persyaratan penyelarasan 4. Baik serikat dan struct dapat memiliki bantalan pada akhirnya, tetapi tidak pada awalnya. Menulis ke struct hanya mengubah nilai anggota yang ditulis. Menulis kepada anggota serikat akan membuat nilai dari semua anggota lainnya tidak valid. Anda tidak dapat mengaksesnya jika Anda belum menulisnya sebelumnya, jika tidak maka perilaku tidak akan ditentukan. GCC menyediakan ekstensi yang benar-benar dapat Anda baca dari anggota serikat, meskipun Anda belum menulis surat kepada mereka baru-baru ini. Untuk Sistem Operasi, tidak masalah apakah program pengguna menulis ke serikat pekerja atau ke struktur. Ini sebenarnya hanya masalah dari kompiler.Properti penting lain dari union dan struct adalah, mereka memungkinkan penunjuk kepada mereka dapat menunjuk ke jenis anggota mana pun . Jadi yang berikut ini valid:
some_test_pointer dapat mengarah ke
int*
ataudouble*
. Jika Anda memasukkan alamat tipetest
keint*
, itu akan menunjuk ke anggota pertamanyaa
,, sebenarnya. Hal yang sama juga berlaku untuk serikat pekerja. Dengan demikian, karena sebuah serikat pekerja akan selalu memiliki perataan yang benar, Anda dapat menggunakan serikat pekerja untuk membuat menunjuk ke beberapa jenis yang valid:Serikat itu benar-benar dapat menunjuk ke int, dan ganda:
sebenarnya valid, sebagaimana dinyatakan oleh standar C99:
Kompiler tidak akan mengoptimalkan
v->a = 10;
karena dapat mempengaruhi nilai*some_int_pointer
(dan fungsi akan kembali10
sebagai ganti5
).sumber
A
union
berguna dalam beberapa skenario.union
dapat menjadi alat untuk manipulasi tingkat yang sangat rendah seperti menulis driver perangkat untuk kernel.Contoh yang membedah
float
sejumlah dengan menggunakanunion
sebuahstruct
dengan bitfields danfloat
. Saya menyimpan nomor difloat
, dan kemudian saya dapat mengakses bagian tertentu darifloat
itustruct
. Contoh menunjukkan bagaimanaunion
digunakan untuk memiliki sudut pandang yang berbeda untuk melihat data.Lihatlah deskripsi presisi tunggal di wikipedia. Saya menggunakan contoh dan angka ajaib 0,15625 dari sana.
union
juga dapat digunakan untuk mengimplementasikan tipe data aljabar yang memiliki banyak alternatif. Saya menemukan contohnya dalam buku "Real World Haskell" karya O'Sullivan, Stewart, dan Goerzen. Lihat di bagian Serikat yang didiskriminasi .Bersulang!
sumber
" union " dan " struct " adalah konstruksi dari bahasa C. Berbicara tentang perbedaan "tingkat OS" di antara mereka tidak pantas, karena itu adalah kompiler yang menghasilkan kode yang berbeda jika Anda menggunakan satu atau kata kunci lain.
sumber
Non teknis berbicara:
Asumsi: kursi = blok memori, orang = variabel
Struktur : Jika ada 3 orang, mereka dapat duduk di kursi sesuai ukuran mereka.
Persatuan : Jika ada 3 orang hanya satu kursi yang akan ada di sana untuk duduk, semua perlu menggunakan kursi yang sama ketika mereka ingin duduk.
Secara teknis berarti:
Program yang disebutkan di bawah ini memberikan penyelaman mendalam ke dalam struktur dan penyatuan bersama.
Total MAIN_STRUCT size = sizeof (UINT64) untuk bufferaddr + sizeof (UNIT32) untuk union + 32 bit untuk bantalan (tergantung pada arsitektur prosesor) = 128 bit. Untuk struktur semua anggota mendapatkan blok memori secara bersamaan.
Union mendapat satu blok memori dari anggota ukuran maksimal (Ini 32 bitnya). Di dalam persatuan satu lagi terletak struktur (INNER_STRUCT) anggotanya mendapatkan blok memori ukuran total 32 bit (16 + 8 + 8). Dalam serikat, INNER_STRUCT (32 bit) anggota atau data (32 bit) dapat diakses.
sumber
Ya, perbedaan utama antara struct dan union adalah sama seperti yang Anda nyatakan. Struct menggunakan semua memori anggota dan serikat menggunakan ruang memori anggota terbesar.
Namun semua perbedaannya terletak pada kebutuhan penggunaan memori. Penggunaan serikat yang terbaik dapat dilihat dalam proses unix di mana kami menggunakan sinyal. seperti suatu proses dapat bertindak hanya pada satu sinyal pada satu waktu. Jadi deklarasi umum adalah:
Dalam hal ini, proses hanya menggunakan memori tertinggi dari semua sinyal. tetapi jika Anda menggunakan struct dalam hal ini, penggunaan memori akan menjadi jumlah semua sinyal. Membuat banyak perbedaan.
Untuk meringkas, Union harus dipilih jika Anda tahu bahwa Anda mengakses salah satu anggota sekaligus.
sumber
Anda memilikinya, itu saja. Namun, pada dasarnya, apa gunanya serikat pekerja?
Anda dapat menempatkan konten lokasi yang sama dari berbagai jenis. Anda harus mengetahui jenis dari apa yang telah Anda simpan di serikat (begitu sering Anda memasukkannya
struct
dengan tag jenis ...).Mengapa ini penting? Tidak benar-benar untuk keuntungan ruang. Ya, Anda bisa mendapatkan beberapa bit atau melakukan padding, tapi itu bukan poin utama lagi.
Ini untuk keamanan jenis, memungkinkan Anda untuk melakukan semacam 'pengetikan dinamis': kompiler tahu bahwa konten Anda mungkin memiliki arti yang berbeda dan makna yang tepat tentang bagaimana Anda menafsirkannya terserah Anda pada saat run-time. Jika Anda memiliki pointer yang dapat menunjuk ke tipe yang berbeda, Anda HARUS menggunakan gabungan, jika tidak, kode Anda mungkin salah karena masalah alias (kompiler mengatakan sendiri "oh, hanya pointer ini yang bisa menunjuk ke tipe ini, jadi saya bisa mengoptimalkan keluar akses itu ... ", dan hal-hal buruk dapat terjadi).
sumber
Struktur mengalokasikan ukuran total semua elemen di dalamnya.
Serikat pekerja hanya mengalokasikan memori sebanyak yang dibutuhkan anggota terbesarnya.
sumber
apa perbedaan antara struktur dan persatuan?
Jawaban pintasan adalah: Deferensi dalam alokasi memori. Penjelasan: Dalam struktur, ruang memori akan dibuat untuk semua anggota di dalam struktur. Dalam penyatuan ruang memori akan dibuat hanya untuk anggota yang membutuhkan ruang memori terbesar. Pertimbangkan kode berikut:
Di sini ada dua anggota di dalam struct dan union: int dan long int. Ruang memori untuk int adalah: 4 byte dan ruang memori untuk int panjang adalah: sistem operasi 8 in 32 bit.
Jadi untuk struct 4 + 8 = 12 byte akan dibuat sedangkan 8 byte akan dibuat untuk union
Contoh kode:
Ref: http://www.codingpractise.com/home/c-programming/structure-and-union/
sumber
Penggunaan serikat pekerja sering digunakan ketika percakapan jenis khusus dibutuhkan. Untuk mendapatkan gagasan tentang kegunaan serikat. Pustaka standar c / c tidak mendefinisikan fungsi yang dirancang khusus untuk menulis bilangan bulat pendek ke file. Menggunakan fwrite () menimbulkan biaya overhead yang berlebihan untuk operasi sederhana. Namun dengan menggunakan gabungan Anda dapat dengan mudah membuat fungsi yang menulis biner integer pendek ke file satu byte pada suatu waktu. Saya berasumsi bahwa bilangan bulat pendek adalah 2 byte
CONTOH:
meskipun putw () saya panggil dengan integer pendek, itu mungkin untuk menggunakan putc () dan fwrite (). Tetapi saya ingin menunjukkan contoh untuk mendominasi bagaimana sebuah serikat dapat digunakan
sumber
struktur adalah kumpulan dari tipe data yang berbeda di mana tipe data yang berbeda dapat tinggal di dalamnya dan setiap orang mendapatkan blok memorinya sendiri
kami biasanya menggunakan gabungan ketika kami yakin bahwa hanya satu dari variabel yang akan digunakan sekaligus dan Anda ingin memanfaatkan sepenuhnya memori saat ini karena hanya mendapatkan satu blok memori yang sama dengan jenis terbesar.
total memori yang didapat => 5 byte
total memori yang didapat = 4 byte
sumber
Serikat pekerja berguna saat menulis fungsi pemesanan byte yang diberikan di bawah ini. Itu tidak mungkin dengan struct.
sumber
Union berbeda dari struct karena Union mengulangi yang lain: itu mendefinisikan ulang memori yang sama sementara struct mendefinisikan satu demi satu tanpa tumpang tindih atau redefinisi.
sumber