sinau-c/content/unions.md

6.4 KiB

---LESSON_INFO--- Learning Objectives:

  • Memahami konsep union dalam bahasa C
  • Belajar membuat dan menggunakan union
  • Mengenal perbedaan antara struct dan union
  • Memahami penggunaan union dalam program

Prerequisites:

  • Pemahaman tentang struct
  • Pemahaman dasar tentang memori dalam program

---END_LESSON_INFO---

Union dalam C

Union dalam C pada dasarnya sama dengan Struktur C, kecuali bahwa bukannya berisi beberapa variabel masing-masing dengan memori sendiri, Union memungkinkan beberapa nama untuk variabel yang sama. Nama-nama ini bisa memperlakukan memori sebagai tipe yang berbeda (dan ukuran union akan menjadi ukuran tipe terbesar, + setiap padding yang mungkin diputuskan kompiler) Jadi jika Anda ingin bisa membaca memori variabel dengan cara yang berbeda, misalnya membaca integer satu byte per satu byte, Anda bisa memiliki sesuatu seperti ini:

union intParts {
    int theInt;
    char bytes[sizeof(int)];
};

Memungkinkan Anda untuk melihat setiap byte secara individual tanpa casting pointer dan menggunakan aritmatika pointer:

union intParts parts;
parts.theInt = 5968145; // angka acak > 255 (1 byte)
printf("The int is %i\\nThe bytes are [%i, %i, %i, %i]\\n", parts.theInt, parts.bytes[0], parts.bytes[1], parts.bytes[2], parts.bytes[3]);
// vs
int theInt = parts.theInt;
printf("The int is %i\\nThe bytes are [%i, %i, %i, %i]\\n", theInt, *((char*)&theInt+0), *((char*)&theInt+1), *((char*)&theInt+2), *((char*)&theInt+3));
// atau dengan sintaks array yang bisa sedikit lebih enak terkadang
printf("The int is %i\\nThe bytes are [%i, %i, %i, %i]\\n", theInt, ((char*)&theInt)[0], ((char*)&theInt)[1], ((char*)&theInt)[2], ((char*)&theInt)[3]);

Menggabungkan ini dengan struktur memungkinkan Anda membuat union "bertag" yang bisa digunakan untuk menyimpan beberapa tipe berbeda, satu per satu. Sebagai contoh, Anda mungkin memiliki struktur "number", tetapi Anda tidak ingin menggunakan sesuatu seperti ini:

struct operator {
    int intNum;
    float floatNum;
    int type;
    double doubleNum;
};

Karena program Anda memiliki banyak dari mereka dan membutuhkan sedikit terlalu banyak memori untuk semua variabel, jadi Anda bisa menggunakan ini:

struct operator {
    int type;
    union {
        int intNum;
        float floatNum;
        double doubleNum;
    } types;
};

Seperti ini ukuran dari struct hanya ukuran dari int type + ukuran dari tipe terbesar dalam union (double). Bukan keuntungan besar, hanya 8 atau 16 byte, tetapi konsep bisa diterapkan ke struct yang mirip.

penggunaan:

operator op;
op.type = 0; // int, mungkin lebih baik sebagai enum atau konstanta makro
op.types.intNum = 352;

Juga, jika Anda tidak memberi nama union maka anggotanya diakses langsung dari struct:

struct operator {
    int type;
    union {
        int intNum;
        float floatNum;
        double doubleNum;
    }; // tanpa nama!
};
operator op;
op.type = 0; // int
// intNum adalah bagian dari union, tetapi karena tidak diberi nama Anda mengaksesnya langsung dari struct itu sendiri
op.intNum = 352;

Fitur lain yang mungkin lebih berguna adalah ketika Anda selalu memiliki beberapa variabel dari tipe yang sama, dan Anda ingin bisa menggunakan baik nama (untuk keterbacaan) dan indeks (untuk kemudahan iterasi), dalam hal ini Anda bisa melakukan sesuatu seperti ini:

union Coins {
    struct {
        int quarter;
        int dime;
        int nickel;
        int penny;
    }; // struct anonim bertindak sama seperti union anonim, anggota berada di kontainer luar
    int coins[4];
};

Dalam contoh itu Anda bisa melihat bahwa ada struct yang berisi empat koin (umum) di Amerika Serikat. karena union membuat variabel berbagi memori array koin cocok dengan setiap int dalam struct (dalam urutan):

union Coins change;
for(int i = 0; i < sizeof(change) / sizeof(int); ++i) {
    scanf("%i", change.coins + i); // kode BURUK! input selalu mencurigakan!
}
printf("There are %i quarters, %i dimes, %i nickels, and %i pennies\\n", change.quarter, change.dime, change.nickel, change.penny);

Tabel Perbedaan Struct dan Union

Fitur Struct Union
Penyimpanan Setiap anggota memiliki alamat memori sendiri Semua anggota berbagi alamat memori yang sama
Ukuran Jumlah ukuran semua anggota Ukuran anggota terbesar
Akses Semua anggota bisa diakses bersamaan Hanya satu anggota yang bisa digunakan pada satu waktu
Keyword struct union

---EXERCISE---

Latihan: Membuat Union untuk Integer dan Karakter

Buat union yang menyimpan array dari 21 karakter dan 6 int (6 karena 21 / 4 == 5, tetapi 5 * 4 == 20 jadi Anda butuh 1 lagi untuk tujuan latihan ini), Anda akan mengatur integer ke 6 nilai yang diberikan dan kemudian mencetak array karakter baik sebagai deretan karakter maupun sebagai string.

Requirements:

  • Buat union dengan array karakter dan array integer
  • Gunakan nilai integer yang diberikan
  • Cetak hasil sebagai karakter dan string

Expected Output:

[I, , u, n, d, e, r, s, t, a, n, d, , U, n, i, o, n, s, !]
I understand Unions!

Try writing your solution in the code editor below!

---EXPECTED_OUTPUT--- [I, , u, n, d, e, r, s, t, a, n, d, , U, n, i, o, n, s, !] I understand Unions! ---END_EXPECTED_OUTPUT---

---INITIAL_CODE--- #include <stdio.h> /* definisikan union di sini */

int main() { // daftar inisialisasi seperti ini diberikan ke anggota pertama dari union/struct! // Ada 6 int di sini jadi... intCharacters = {{1853169737, 1936876900, 1684955508, 1768838432, 561213039, 0}}; /* kode pengujian */ printf("["); // hanya pergi ke 18 karena 1 byte untuk terminasi 0 dan kita tidak mencetak yang terakhir dalam loop for(int i = 0; i < 19; ++i) printf("%c, ", intCharacters.chars[i]); printf("%c]\n", intCharacters.chars[19]); printf("%s\n", intCharacters.chars); } ---END_INITIAL_CODE---

---SOLUTION_CODE--- #include <stdio.h> union hiddenMessage { int ints[6]; char chars[21]; };

int main() { union hiddenMessage intCharacters = {{1853169737, 1936876900, 1684955508, 1768838432, 561213039, 0}}; printf("["); // hanya pergi ke 18 karena 1 byte untuk terminasi 0 dan kita tidak mencetak yang terakhir dalam loop for(int i = 0; i < 19; ++i) printf("%c, ", intCharacters.chars[i]); printf("%c]\n", intCharacters.chars[19]); printf("%s\n", intCharacters.chars); } ---END_SOLUTION_CODE---