Pelajari Bahasa Pemrograman C Tertanam:Memahami Objek Data Union
Pelajari tentang objek data yang disebut union dalam bahasa C yang disematkan.
Pelajari tentang objek data yang disebut union dalam bahasa C yang disematkan.
Perbedaan Antara Struktur dan Union dalam Embedded C
Dalam artikel sebelumnya dari seri ini, kita telah membahas bahwa struktur dalam C yang disematkan memungkinkan kita untuk mengelompokkan variabel dari tipe data yang berbeda dan menanganinya sebagai objek data tunggal.
Selain struktur, bahasa C mendukung konstruksi data lain, yang disebut gabungan, yang dapat mengelompokkan tipe data yang berbeda sebagai objek data tunggal. Artikel ini akan memberikan beberapa informasi dasar tentang serikat pekerja. Pertama-tama kita akan melihat contoh pengantar untuk mendeklarasikan gabungan, lalu kita akan memeriksa aplikasi penting dari objek data ini.
Contoh Pendahuluan
Mendeklarasikan serikat pekerja sama seperti mendeklarasikan struktur. Kita hanya perlu mengganti kata kunci “struct” dengan “union”. Perhatikan contoh kode berikut:
uji serikat { uint8_t c; uint32_t i;};
Ini menentukan template yang memiliki dua anggota:“c”, yang membutuhkan satu byte, dan “i”, yang menempati empat byte.
Sekarang, kita dapat membuat variabel dari template gabungan ini:
uji serikat u1;
Menggunakan operator anggota (.), kita dapat mengakses anggota serikat "u1". Misalnya, kode berikut memberikan 10 ke anggota kedua dari gabungan di atas dan menyalin nilai "c" ke variabel "m" (yang harus bertipe uint8_t).
u1.i=10;m=u1.c;
Berapa banyak ruang memori yang akan dialokasikan untuk menyimpan variabel "u1"? Sedangkan ukuran suatu struktur setidaknya sama besar dengan jumlah ukuran anggotanya, ukuran serikat pekerja sama dengan ukuran variabel terbesarnya. Ruang memori yang dialokasikan untuk serikat pekerja akan dibagi di antara semua anggota serikat pekerja. Dalam contoh di atas, ukuran "u1" sama dengan ukuran uint32_t, yaitu empat byte. Ruang memori ini dibagi antara "i" dan "c". Oleh karena itu, menetapkan nilai ke salah satu dari dua anggota ini akan mengubah nilai anggota lainnya.
Anda mungkin bertanya-tanya, "Apa gunanya menggunakan ruang memori yang sama untuk menyimpan banyak variabel? Apakah ada aplikasi untuk fitur ini?" Kami akan mengeksplorasi masalah ini di bagian berikutnya.
Apakah Kita Membutuhkan Ruang Memori Bersama?
Mari kita lihat contoh di mana serikat pekerja dapat menjadi objek data yang berguna. Asumsikan bahwa, seperti yang ditunjukkan pada Gambar 1 di bawah, ada dua perangkat di sistem Anda yang perlu berkomunikasi satu sama lain.
Gambar 1
"Perangkat A" harus mengirim informasi status, kecepatan, dan posisi ke "Perangkat B". Informasi status terdiri dari tiga variabel yang menunjukkan pengisian daya baterai, mode pengoperasian, dan suhu sekitar. Posisi diwakili oleh dua variabel yang menunjukkan posisi sumbu x dan y. Akhirnya, kecepatan diwakili oleh variabel tunggal. Asumsikan ukuran variabel ini seperti yang ditunjukkan pada tabel berikut.
Nama Variabel | Ukuran (Byte) | Penjelasan |
kekuatan | 1 | Pengisian Daya Baterai |
op_mode | 1 | Mode Operasi |
temp | 1 | Suhu |
x_pos | 2 | Posisi X |
y_pos | 2 | Posisi Y |
vel | 2 | Kecepatan |
Jika "Perangkat B" terus-menerus perlu memiliki setiap bagian dari informasi ini, kami dapat menyimpan semua variabel ini dalam sebuah struktur dan mengirimkan struktur tersebut ke "Perangkat B". Ukuran struktur setidaknya akan sama besar dengan jumlah ukuran variabel-variabel ini, yaitu, sembilan byte.
Jadi, setiap kali "Perangkat A" berbicara dengan "Perangkat B", ia perlu mentransfer bingkai data 9-byte melalui tautan komunikasi antara kedua perangkat. Gambar 2 menggambarkan struktur yang digunakan “Perangkat A” untuk menyimpan variabel dan kerangka data yang perlu melalui tautan komunikasi.
Gambar 2
Namun, mari kita pertimbangkan skenario yang berbeda di mana kita hanya sesekali perlu mengirim informasi status. Juga, anggaplah tidak perlu memiliki informasi posisi dan kecepatan pada waktu tertentu. Dengan kata lain, terkadang kami hanya mengirim posisi, terkadang kami hanya mengirim kecepatan, dan terkadang kami hanya mengirim informasi status. Dalam situasi ini, sepertinya bukan ide yang baik untuk menyimpan informasi dalam struktur sembilan byte dan mentransfernya melalui tautan komunikasi.
Informasi status hanya dapat diwakili oleh tiga byte; untuk posisi dan kecepatan, kita masing-masing hanya membutuhkan empat dan dua byte. Oleh karena itu, jumlah byte maksimum yang perlu dikirim oleh "Perangkat A" dalam satu transfer adalah empat, dan akibatnya, kami hanya memerlukan empat byte memori untuk menyimpan informasi ini. Ruang memori empat byte ini akan dibagi di antara tiga jenis pesan kami (lihat Gambar 3).
Selain itu, perhatikan bahwa panjang bingkai data yang melewati tautan komunikasi berkurang dari sembilan byte menjadi empat byte.
Gambar 3
Untuk meringkas, jika program kita memiliki variabel yang saling eksklusif, kita dapat menyimpannya di area memori bersama untuk melestarikan ruang memori yang berharga. Ini bisa menjadi penting, terutama dalam konteks sistem tertanam yang dibatasi memori. Dalam kasus seperti itu, kita dapat menggunakan serikat pekerja untuk membuat ruang memori bersama yang diperlukan.
Contoh di atas menunjukkan bahwa menggunakan gabungan untuk menangani variabel yang saling eksklusif juga dapat membantu kita menghemat bandwidth komunikasi. Menghemat bandwidth komunikasi terkadang lebih penting daripada menghemat memori.
Menggunakan Serikat untuk Paket Pesan
Mari kita lihat bagaimana kita dapat menggunakan gabungan untuk menyimpan variabel dari contoh di atas. Kami memiliki tiga jenis pesan yang berbeda:status, posisi, dan kecepatan. Kita dapat membuat struktur untuk variabel pesan status dan posisi (sehingga variabel pesan ini dikelompokkan dan dimanipulasi sebagai objek data tunggal).
Struktur berikut melayani tujuan ini:
struct { uint8_t power; unit8_t op_mode; uint8_t temp;} status;struct { uint16_t x_pos; unit16_t y_pos;} posisi;
Sekarang, kita dapat menempatkan struktur ini bersama dengan variabel "vel" dalam satu kesatuan:
union {struct { uint8_t power; unit8_t op_mode; uint8_t temp;} status;struct { uint16_t x_pos; unit16_t y_pos;} posisi; uint16_t vel;} msg_union;
Kode di atas menentukan template serikat dan membuat variabel dari template ini (bernama “msg_union”). Di dalam serikat ini, ada dua struktur ("status" dan "posisi") dan variabel dua byte ("vel"). Ukuran persatuan ini akan sama dengan ukuran anggota terbesarnya, yaitu, struktur "posisi", yang menempati empat byte memori. Ruang memori ini dibagi di antara variabel “status”, “posisi”, dan “vel”.
Cara Melacak Anggota Aktif Union
Kita dapat menggunakan ruang memori bersama dari gabungan di atas untuk menyimpan variabel kita; namun, masih ada satu pertanyaan:Bagaimana penerima menentukan jenis pesan yang telah dikirim? Penerima perlu mengenali jenis pesan agar dapat berhasil menginterpretasikan informasi yang diterima. Misalnya, jika kita mengirim pesan “posisi”, keempat byte data yang diterima adalah penting, tetapi untuk pesan “kecepatan”, hanya dua byte yang diterima yang harus digunakan.
Untuk mengatasi masalah ini, kita perlu mengaitkan serikat kita dengan variabel lain, katakan "msg_type", yang menunjukkan jenis pesan (atau anggota serikat yang terakhir ditulis). Serikat pekerja yang dipasangkan dengan nilai diskrit yang menunjukkan anggota aktif serikat pekerja disebut “serikat yang didiskriminasi” atau “serikat bertanda”.
Mengenai tipe data untuk variabel “msg_type”, kita dapat menggunakan tipe data enumerasi bahasa C untuk membuat konstanta simbolis. Namun, kami akan menggunakan karakter untuk menentukan jenis pesan, hanya untuk membuat semuanya sesederhana mungkin:
struct { uint8_t msg_type;union {struct { uint8_t power; unit8_t op_mode; uint8_t temp;} status;struct { uint16_t x_pos; unit16_t y_pos;} posisi; uint16_t vel;} msg_union;} pesan;
Kita dapat mempertimbangkan tiga kemungkinan nilai untuk variabel "msg_type":'s' untuk pesan "status", 'p' untuk pesan "posisi", dan 'v' untuk pesan "kecepatan". Sekarang, kita dapat mengirim struktur "pesan" ke "Perangkat B" dan menggunakan nilai variabel "msg_type" sebagai indikator jenis pesan. Misalnya, jika nilai "msg_type" yang diterima adalah 'p', "Perangkat B" akan mengetahui bahwa ruang memori bersama berisi dua variabel 2-byte.
Perhatikan bahwa kita harus menambahkan byte lain ke bingkai data yang dikirim melalui tautan komunikasi karena kita perlu mentransfer variabel "msg_type". Perhatikan juga bahwa, dengan solusi ini, penerima tidak perlu mengetahui sebelumnya jenis pesan apa yang masuk.
Solusi Alternatif:Alokasi Memori Dinamis
Kami melihat bahwa union memungkinkan kami untuk mendeklarasikan area memori bersama untuk menghemat ruang memori dan bandwidth komunikasi. Namun, ada cara lain untuk menyimpan variabel yang saling eksklusif seperti pada contoh di atas. Solusi kedua ini menggunakan alokasi memori dinamis untuk menyimpan variabel dari setiap jenis pesan.
Sekali lagi, kita perlu memiliki variabel "msg_type" untuk menentukan jenis pesan di ujung pemancar dan penerima dari tautan komunikasi. Misalnya, jika "Perangkat A" perlu mengirim pesan posisi, itu akan mengatur "msg_type" ke 'p' dan mengalokasikan empat byte ruang memori untuk menyimpan variabel "x_pos" dan "y_pos". Penerima akan memeriksa nilai “msg_type” dan, bergantung pada nilainya, membuat ruang memori yang sesuai untuk menyimpan dan menafsirkan bingkai data yang masuk.
Penggunaan memori dinamis dapat lebih efisien dalam hal penggunaan memori karena kami mengalokasikan ruang yang cukup untuk setiap jenis pesan. Ini tidak terjadi dengan solusi berbasis serikat pekerja. Di sana, kami memiliki empat byte memori bersama untuk menyimpan ketiga jenis pesan, meskipun pesan "status" dan "kecepatan" masing-masing hanya membutuhkan tiga dan dua byte. Namun, alokasi memori dinamis bisa lebih lambat, dan programmer perlu memasukkan kode yang membebaskan memori yang dialokasikan. Itu sebabnya programmer biasanya lebih suka menggunakan solusi berbasis serikat pekerja.
Selanjutnya:Aplikasi Serikat Pekerja
Tampaknya tujuan awal serikat pekerja adalah menciptakan area memori bersama untuk variabel yang saling eksklusif. Namun, union juga telah banyak digunakan untuk mengekstrak bagian data yang lebih kecil dari objek data yang lebih besar.
Artikel berikutnya dalam seri ini akan berfokus pada penerapan serikat pekerja ini, yang dapat menjadi sangat penting dalam aplikasi yang disematkan.
Untuk melihat daftar lengkap artikel saya, silakan kunjungi halaman ini.