網頁

2022/8/1

C++ union 簡介

C++ union關鍵字可用來定義union型別。


Union與struct用法非常類似,但差別在於union成員共用一個記憶體空間,持有的記憶體空間會以成員中佔最大的為準;而struct成員則擁有各自的記憶體空間。Union的好處就是節省記憶體空間及效能,當資料有多種不同型別表示的樣態時可使用union表示。


宣告union

宣告union型別的語法如下:

  • union - 宣告union的關鍵字。
  • TypeName - Union的名稱,習慣以UpperCamelCase命名。
  • member_type1-3 - Union的成員型態。成員(member)是union所含的各種資料型態,如intdouble,或陣列(array)類別(class)string、struct、另一union。
  • member_name1-3 - Union的成員名稱。
union TypeName {
    member_type1 member_name1;
    member_type2 member_name2;
    member_type3 member_name3;
    ...
};

例如下面宣告一個union型別名為ASCII,有兩個成員short int d(佔用2 bytes)及char c(佔用1 byte),則此union佔的記憶體空間為2 bytes。

union ASCII {
    short int d; // 2 bytes
    char c;      // 1 byte
};


Union初始化

由於union成員共用一記憶體空間,因此在初始化時只能設定一個成員的值,否則會出現error: excess elements in union initializer錯誤。

main.cpp

#include <iostream>

union ASCII {
    short int d;
    char c;
};

int main() {
    // ASCII ascii = {97, 'a'}; // error: excess elements in union initializer
    ASCII ascii = {.c = 'a'};

    return 0;
}


範例

下面宣告union ASCII型別變數asicc,修改成員的值並印出另個成員的值及以bitset表示的二進位。

main.cpp

#include <bitset>
#include <iostream>
using namespace std;

union ASCII {
    short int d; // 2 bytes
    char c;      // 1 byte
};

int main() {
    ASCII ascii;
    ascii.d = 97;

    cout << ascii.d << endl;            // 97 (decimal)
    cout << ascii.c << endl;            // a (char)
    cout << bitset<7>(ascii.d) << endl; // 1100001 (binary)

    ascii.c = 'b';
    cout << ascii.d << endl;            // 98 (decimal)
    cout << ascii.c << endl;            // b (char)
    cout << bitset<7>(ascii.d) << endl; // 1100010 (binary)

    cout << sizeof(ascii) << endl; // 2

    return 0;
}

由於union的成員使用的是同一個記憶體空間,當一個成員被更新時,另一個成員的記憶體內容也被影響。下圖為二進位表示的記憶體空間。

                             ASCII.d = 97
┌────────────────────────────────┴────────────────────────────────┐
┌───┬───┬───┬───┬───┬───┬───┬───┐ ┌───┬───┬───┬───┬───┬───┬───┬───┐
│ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │ │ 0 │ 1 │ 1 │ 0 │ 0 │ 0 │ 0 │ 1 │
└───┴───┴───┴───┴───┴───┴───┴───┘ └───┴───┴───┴───┴───┴───┴───┴───┘
└────────────────────────────────┬────────────────────────────────┘
                             ASCII.c = 'a'
                             ASCII.d = 98
┌────────────────────────────────┴────────────────────────────────┐
┌───┬───┬───┬───┬───┬───┬───┬───┐ ┌───┬───┬───┬───┬───┬───┬───┬───┐
│ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │ │ 0 │ 1 │ 1 │ 0 │ 0 │ 0 │ 1 │ 0 │
└───┴───┴───┴───┴───┴───┴───┴───┘ └───┴───┴───┴───┴───┴───┴───┴───┘
└────────────────────────────────┬────────────────────────────────┘
                             ASCII.c = 'b'


沒有留言:

張貼留言