ประเภทข้อมูล

ในส่วนนี้จะอธิบายประเภทข้อมูล HIDL สำหรับรายละเอียดการใช้งาน โปรดดูที่ HIDL C++ (สำหรับการใช้งาน C++) หรือ HIDL Java (สำหรับการใช้งาน Java)

ความคล้ายคลึงกับ C ++ รวมถึง:

  • structs ใช้ไวยากรณ์ C ++; unions สนับสนุนไวยากรณ์ C++ ตามค่าเริ่มต้น จะต้องตั้งชื่อทั้งสอง ไม่รองรับโครงสร้างและสหภาพที่ไม่ระบุชื่อ
  • อนุญาตให้ใช้ Typedef ใน HIDL (เช่นเดียวกับใน C ++)
  • อนุญาตให้ใช้ความคิดเห็นสไตล์ C++ และคัดลอกไปยังไฟล์ส่วนหัวที่สร้างขึ้น

ความคล้ายคลึงกับ Java ได้แก่ :

  • สำหรับแต่ละไฟล์ HIDL จะกำหนดเนมสเปซสไตล์ Java ที่ต้องขึ้นต้นด้วย android.hardware. . เนมสเปซ C ++ ที่สร้างขึ้นคือ ::android::hardware::…
  • คำจำกัดความทั้งหมดของไฟล์มีอยู่ภายใน wrapper interface สไตล์ Java
  • การประกาศอาร์เรย์ HIDL เป็นไปตามสไตล์ Java ไม่ใช่สไตล์ C++ ตัวอย่าง:
    struct Point {
        int32_t x;
        int32_t y;
    };
    Point[3] triangle;   // sized array
    
  • ความคิดเห็นจะคล้ายกับรูปแบบ javadoc

การแสดงข้อมูล

struct หรือ union ที่ประกอบด้วย เค้าโครงมาตรฐาน (ชุดย่อยของข้อกำหนดของประเภทข้อมูลเก่าธรรมดา) มีเค้าโครงหน่วยความจำที่สอดคล้องกันในโค้ด C++ ที่สร้างขึ้น ซึ่งบังคับใช้ด้วยแอตทริบิวต์การจัดตำแหน่งที่ชัดเจนใน struct และสมาชิก union

ประเภท HIDL ดั้งเดิม เช่นเดียวกับประเภท enum และ bitfield (ซึ่งมักจะมาจากประเภทดั้งเดิม) แมปกับประเภท C++ มาตรฐาน เช่น std::uint32_t จาก cstdint

เนื่องจาก Java ไม่รองรับประเภทที่ไม่ได้ลงนาม ประเภท HIDL ที่ไม่ได้ลงนามจึงถูกแมปกับประเภท Java ที่ลงนามที่สอดคล้องกัน โครงสร้าง แมปกับคลาส Java; อาร์เรย์ แมปกับอาร์เรย์ Java; ขณะนี้ยังไม่รองรับ สหภาพแรงงาน ใน Java สตริง จะถูกจัดเก็บภายในเป็น UTF8 เนื่องจาก Java รองรับเฉพาะสตริง UTF16 ค่าสตริงที่ส่งไปยังหรือจากการใช้งาน Java จะถูกแปล และอาจไม่เหมือนกันในการแปลใหม่ เนื่องจากชุดอักขระไม่ได้แมปอย่างราบรื่นเสมอไป

ข้อมูลที่ได้รับผ่าน IPC ใน C++ ถูกทำเครื่องหมายว่า const และอยู่ในหน่วยความจำแบบอ่านอย่างเดียวซึ่งคงอยู่เฉพาะในช่วงระยะเวลาของการเรียกใช้ฟังก์ชันเท่านั้น ข้อมูลที่ได้รับผ่าน IPC ใน Java ได้ถูกคัดลอกไปยังอ็อบเจ็กต์ Java แล้ว ดังนั้นจึงสามารถเก็บรักษาไว้ได้โดยไม่ต้องคัดลอกเพิ่มเติม (และอาจได้รับการแก้ไข)

คำอธิบายประกอบ

คำอธิบายประกอบแบบ Java อาจถูกเพิ่มลงในการประกาศประเภท คำอธิบายประกอบจะถูกแยกวิเคราะห์โดยแบ็กเอนด์ Vendor Test Suite (VTS) ของคอมไพเลอร์ HIDL แต่คอมไพเลอร์ HIDL ไม่เข้าใจคำอธิบายประกอบที่แยกวิเคราะห์ดังกล่าวจริงๆ แต่คำอธิบายประกอบ VTS ที่แยกวิเคราะห์จะถูกจัดการโดย VTS Compiler (VTSC) แทน

คำอธิบายประกอบใช้ไวยากรณ์ Java: @annotation หรือ @annotation(value) หรือ @annotation(id=value, id=value…) โดยที่ value อาจเป็นนิพจน์คงที่ สตริง หรือรายการของค่าภายใน {} เช่นเดียวกับใน ชวา คุณสามารถแนบคำอธิบายประกอบหลายรายการที่มีชื่อเดียวกันลงในรายการเดียวกันได้

ประกาศไปข้างหน้า

ใน HIDL โครงสร้างไม่สามารถถูกประกาศไปข้างหน้า ซึ่งทำให้ประเภทข้อมูลที่ผู้ใช้กำหนดและอ้างอิงตนเองเป็นไปไม่ได้ (เช่น คุณไม่สามารถอธิบายรายการที่เชื่อมโยงหรือแผนผังใน HIDL) HAL ที่มีอยู่ส่วนใหญ่ (ก่อน Android 8.x) มีการใช้งานการประกาศไปข้างหน้าอย่างจำกัด ซึ่งสามารถลบออกได้โดยการจัดเรียงการประกาศโครงสร้างข้อมูลใหม่

ข้อจำกัดนี้อนุญาตให้คัดลอกโครงสร้างข้อมูลตามค่าด้วยการคัดลอกเชิงลึกอย่างง่าย แทนที่จะติดตามค่าตัวชี้ที่อาจเกิดขึ้นหลายครั้งในโครงสร้างข้อมูลอ้างอิงตัวเอง หากข้อมูลเดียวกันถูกส่งสองครั้ง เช่น ด้วยพารามิเตอร์เมธอดสองตัวหรือ vec<T> ที่ชี้ไปยังข้อมูลเดียวกัน จะมีการสร้างและจัดส่งสำเนาสองชุดแยกกัน

การประกาศที่ซ้อนกัน

HIDL รองรับการประกาศแบบซ้อนได้หลายระดับตามต้องการ (โดยมีข้อยกเว้นหนึ่งข้อที่ระบุไว้ด้านล่าง) ตัวอย่างเช่น:

interface IFoo {
    uint32_t[3][4][5][6] multidimArray;

    vec<vec<vec<int8_t>>> multidimVector;

    vec<bool[4]> arrayVec;

    struct foo {
        struct bar {
            uint32_t val;
        };
        bar b;
    }
    struct baz {
        foo f;
        foo.bar fb; // HIDL uses dots to access nested type names
    }
    …

ข้อยกเว้นคือประเภทอินเทอร์เฟซสามารถฝังได้ใน vec<T> และลึกเพียงระดับเดียวเท่านั้น (ไม่มี vec<vec<IFoo>> )

ไวยากรณ์ตัวชี้ดิบ

ภาษา HIDL ไม่ได้ใช้ * และไม่รองรับความยืดหยุ่นเต็มที่ของพอยน์เตอร์ดิบ C/C++ สำหรับรายละเอียดเกี่ยวกับวิธีที่ HIDL ห่อหุ้มพอยน์เตอร์และอาร์เรย์/เวกเตอร์ โปรดดู เทมเพลต vec<T>

อินเทอร์เฟซ

คีย์เวิร์ด interface เทอร์เฟซมีการใช้งานสองแบบ

  • จะเปิดคำจำกัดความของอินเทอร์เฟซในไฟล์ .hal
  • สามารถใช้เป็นชนิดพิเศษในฟิลด์โครงสร้าง/สหภาพ พารามิเตอร์เมธอด และการส่งคืน มันถูกมองว่าเป็นอินเทอร์เฟซทั่วไปและคำพ้องความหมายกับ android.hidl.base@1.0::IBase

ตัวอย่างเช่น IServiceManager มีวิธีการดังต่อไปนี้:

get(string fqName, string name) generates (interface service);

วิธีการสัญญาว่าจะค้นหา อินเทอร์เฟซ ตามชื่อ นอกจากนี้ยังเหมือนกับการแทนที่อินเทอร์เฟซด้วย android.hidl.base@1.0::IBase

อินเทอร์เฟซสามารถส่งผ่านได้สองวิธีเท่านั้น: เป็นพารามิเตอร์ระดับบนสุด หรือเป็นสมาชิกของ vec<IMyInterface> ไม่สามารถเป็นสมาชิกของ vec, structs, array หรือ union ที่ซ้อนกันได้

MQDescriptorSync และ MQDescriptorUnsync

ประเภท MQDescriptorSync และ MQDescriptorUnsync จะส่งผ่านตัวอธิบาย Fast Message Queue (FMQ) ที่ซิงโครไนซ์หรือไม่ซิงโครไนซ์ผ่านอินเทอร์เฟซ HIDL สำหรับรายละเอียด โปรดดู HIDL C++ (Java ไม่รองรับ FMQ)

ประเภทหน่วยความจำ

ประเภทหน่วย memory ใช้เพื่อแสดงหน่วยความจำที่ใช้ร่วมกันที่ไม่ได้แมปใน HIDL รองรับเฉพาะในภาษา C++ เท่านั้น ค่าประเภทนี้สามารถใช้ในส่วนรับเพื่อเริ่มต้นวัตถุ IMemory การแมปหน่วยความจำ และทำให้สามารถใช้งานได้ สำหรับรายละเอียด โปรดดูที่ HIDL C++

คำเตือน: ข้อมูลที่มีโครงสร้างที่วางอยู่ในหน่วยความจำที่ใช้ร่วมกันต้องเป็นประเภทที่รูปแบบจะไม่เปลี่ยนแปลงตลอดอายุการใช้งานของเวอร์ชันอินเทอร์เฟซที่ส่งผ่าน memory มิฉะนั้น HAL อาจประสบปัญหาความเข้ากันได้ร้ายแรง

ประเภทตัวชี้

ประเภท pointer มีไว้สำหรับใช้ภายใน HIDL เท่านั้น

เทมเพลตประเภท bitfield<T>

bitfield<T> โดยที่ T เป็น enum ที่ผู้ใช้กำหนด แนะนำว่าค่านั้นเป็น bitwise-OR ของค่า enum ที่กำหนดใน T ในโค้ดที่สร้างขึ้น bitfield<T> จะปรากฏเป็นประเภทพื้นฐานของ T ตัวอย่างเช่น:

enum Flag : uint8_t {
    HAS_FOO = 1 << 0,
    HAS_BAR = 1 << 1,
    HAS_BAZ = 1 << 2
};
typedef bitfield<Flag> Flags;
setFlags(Flags flags) generates (bool success);

คอมไพเลอร์จัดการประเภท Flags เช่นเดียวกับ uint8_t

ทำไมไม่ใช้ (u)int8_t / (u)int16_t / (u)int32_t / (u)int64_t ? การใช้ bitfield จะให้ข้อมูล HAL เพิ่มเติมแก่ผู้อ่าน ซึ่งขณะนี้ทราบแล้วว่า setFlags รับค่าระดับบิตหรือหรือของ Flag (เช่น รู้ว่าการเรียก setFlags ด้วย 16 นั้นไม่ถูกต้อง) หากไม่มี bitfield ข้อมูลนี้จะถูกส่งผ่านเอกสารประกอบเท่านั้น นอกจากนี้ VTS ยังสามารถตรวจสอบได้ว่าค่าของแฟล็กเป็นค่าบิตหรือของแฟล็กหรือไม่

จัดการประเภทดั้งเดิม

คำเตือน: ที่อยู่ทุกชนิด (แม้แต่ที่อยู่อุปกรณ์จริง) จะต้องไม่เป็นส่วนหนึ่งของหมายเลขอ้างอิงดั้งเดิม การส่งข้อมูลนี้ระหว่างกระบวนการต่างๆ ถือเป็นอันตรายและทำให้เสี่ยงต่อการถูกโจมตีได้ ค่าใดๆ ที่ส่งผ่านระหว่างกระบวนการจะต้องได้รับการตรวจสอบก่อนจึงจะถูกนำมาใช้เพื่อค้นหาหน่วยความจำที่จัดสรรภายในกระบวนการ มิฉะนั้น หมายเลขอ้างอิงที่ไม่ถูกต้องอาจทำให้การเข้าถึงหน่วยความจำไม่ดีหรือหน่วยความจำเสียหาย

ซีแมนทิกส์ HIDL เป็นการคัดลอกตามค่า ซึ่งหมายความว่าพารามิเตอร์ถูกคัดลอก ข้อมูลขนาดใหญ่ใดๆ หรือข้อมูลที่จำเป็นต้องแบ่งปันระหว่างกระบวนการต่างๆ (เช่น รั้วการซิงค์) จะได้รับการจัดการโดยการส่งผ่านตัวอธิบายไฟล์ที่ชี้ไปยังออบเจ็กต์ถาวร: ashmem สำหรับหน่วยความจำที่ใช้ร่วมกัน ไฟล์จริง หรือสิ่งอื่นใดที่สามารถซ่อนไว้เบื้องหลัง ตัวอธิบายไฟล์ โปรแกรมควบคุมเครื่องผูกจะทำซ้ำตัวอธิบายไฟล์ในกระบวนการอื่น

Native_handle_t

Android รองรับ native_handle_t ซึ่งเป็นแนวคิดการจัดการทั่วไปที่กำหนดไว้ใน libcutils

typedef struct native_handle
{
  int version;        /* sizeof(native_handle_t) */
  int numFds;         /* number of file-descriptors at &data[0] */
  int numInts;        /* number of ints at &data[numFds] */
  int data[0];        /* numFds + numInts ints */
} native_handle_t;

ตัวจัดการเนทิฟคือชุดของ ints และตัวอธิบายไฟล์ที่ถูกส่งผ่านตามค่า ตัวอธิบายไฟล์เดียวสามารถจัดเก็บไว้ในตัวจัดการดั้งเดิมโดยไม่มี ints และตัวอธิบายไฟล์ตัวเดียว การส่งผ่านแฮนเดิลโดยใช้แฮนเดิลดั้งเดิมที่ห่อหุ้มด้วย handle ชนิดดั้งเดิมทำให้มั่นใจได้ว่าแฮนเดิลดั้งเดิมจะรวมอยู่ใน HIDL โดยตรง

เนื่องจาก native_handle_t มีขนาดที่แปรผันได้ จึงไม่สามารถรวมไว้ในโครงสร้างโดยตรงได้ ฟิลด์หมายเลขอ้างอิงจะสร้างตัวชี้ไปยัง native_handle_t ที่จัดสรรแยกต่างหาก

ใน Android เวอร์ชันก่อนหน้า ตัวจัดการดั้งเดิมถูกสร้างขึ้นโดยใช้ฟังก์ชันเดียวกันที่มีอยู่ใน libcutils ใน Android 8.0 และสูงกว่า ฟังก์ชันเหล่านี้จะถูกคัดลอกไปยังเนมสเปซ android::hardware::hidl หรือย้ายไปที่ NDK รหัสที่สร้างอัตโนมัติ HIDL จะซีเรียลไลซ์และดีซีเรียลไลซ์ฟังก์ชันเหล่านี้โดยอัตโนมัติ โดยไม่เกี่ยวข้องกับโค้ดที่ผู้ใช้เขียน

จัดการและเป็นเจ้าของตัวอธิบายไฟล์

เมื่อคุณเรียกเมธอดอินเทอร์เฟซ HIDL ที่ส่ง (หรือส่งคืน) วัตถุ hidl_handle (ทั้งระดับบนสุดหรือส่วนหนึ่งของประเภทผสม) ความเป็นเจ้าของไฟล์ descriptors ที่มีอยู่ในนั้นจะเป็นดังนี้:

  • ผู้เรียก ที่ส่งวัตถุ hidl_handle เป็นอาร์กิวเมนต์ยังคงรักษาความเป็นเจ้าของตัวอธิบายไฟล์ที่มีอยู่ใน native_handle_t ที่มันล้อมรอบ ผู้เรียกจะต้องปิดตัวอธิบายไฟล์เหล่านี้เมื่อเสร็จสิ้น
  • กระบวนการ ส่งคืนอ็อบเจ็กต์ hidl_handle (โดยส่งผ่านไปยังฟังก์ชัน _cb ) ยังคงความเป็นเจ้าของตัวอธิบายไฟล์ที่มีอยู่ใน native_handle_t ที่ห่อหุ้มด้วยอ็อบเจ็กต์ กระบวนการจะต้องปิดตัวอธิบายไฟล์เหล่านี้เมื่อเสร็จสิ้น
  • การขนส่ง ที่ได้รับ hidl_handle มีความเป็นเจ้าของตัวอธิบายไฟล์ภายใน native_handle_t ที่ห่อด้วยอ็อบเจ็กต์ ผู้รับสามารถใช้ตัวอธิบายไฟล์เหล่านี้ตามที่เป็นอยู่ในระหว่างการติดต่อกลับของธุรกรรม แต่ต้องโคลนหมายเลขอ้างอิงดั้งเดิมเพื่อใช้ตัวอธิบายไฟล์นอกเหนือจากการโทรกลับ การขนส่งจะ close() ตัวอธิบายไฟล์โดยอัตโนมัติเมื่อธุรกรรมเสร็จสิ้น

HIDL ไม่รองรับการจัดการใน Java (เนื่องจาก Java ไม่รองรับการจัดการเลย)

อาร์เรย์ขนาด

สำหรับอาร์เรย์ที่มีขนาดในโครงสร้าง HIDL องค์ประกอบสามารถเป็นประเภทใดก็ได้ที่โครงสร้างสามารถมีได้:

struct foo {
uint32_t[3] x; // array is contained in foo
};

สตริง

สตริงจะปรากฏแตกต่างกันใน C++ และ Java แต่ประเภทการจัดเก็บข้อมูลการขนส่งที่สำคัญคือโครงสร้าง C++ สำหรับรายละเอียด โปรดดู ประเภทข้อมูล HIDL C++ หรือ ประเภทข้อมูล HIDL Java

หมายเหตุ: การส่งสตริงไปยังหรือจาก Java ผ่านอินเทอร์เฟซ HIDL (รวมถึง Java ไปยัง Java) จะทำให้เกิดการแปลงชุดอักขระที่อาจไม่ได้รักษาการเข้ารหัสดั้งเดิมไว้อย่างแน่นอน

เทมเพลตประเภท vec<T>

เทมเพลต vec<T> แสดงถึงบัฟเฟอร์ขนาดแปรผันที่มีอินสแตนซ์ของ T

T สามารถเป็นหนึ่งในสิ่งต่อไปนี้:

  • ประเภทดั้งเดิม (เช่น uint32_t)
  • สตริง
  • การแจงนับที่ผู้ใช้กำหนด
  • โครงสร้างที่ผู้ใช้กำหนด
  • อินเทอร์เฟซหรือคีย์เวิร์ด interface ( vec<IFoo> , vec<interface> ได้รับการสนับสนุนเป็นพารามิเตอร์ระดับบนสุดเท่านั้น)
  • ที่จับ
  • บิตฟิลด์<U>
  • vec<U> โดยที่ U อยู่ในรายการนี้ยกเว้นอินเทอร์เฟซ (เช่น ไม่รองรับ vec<vec<IFoo>> )
  • U[] (อาร์เรย์ขนาดของ U) โดยที่ U อยู่ในรายการนี้ยกเว้นอินเทอร์เฟซ

ประเภทที่ผู้ใช้กำหนด

ส่วนนี้จะอธิบายประเภทที่ผู้ใช้กำหนด

เอนัม

HIDL ไม่รองรับการแจงนับที่ไม่ระบุชื่อ มิฉะนั้น enums ใน HIDL จะคล้ายกับ C++11:

enum name : type { enumerator , enumerator = constexpr , …  }

enum ฐานถูกกำหนดในแง่ของหนึ่งในประเภทจำนวนเต็มใน HIDL หากไม่มีการระบุค่าสำหรับตัวแจงนับตัวแรกของการแจงนับตามประเภทจำนวนเต็ม ค่าดีฟอลต์จะเป็น 0 หากไม่มีการระบุค่าสำหรับตัวแจงนับในภายหลัง ค่าดีฟอลต์จะเป็นค่าก่อนหน้าบวกหนึ่ง ตัวอย่างเช่น:

// RED == 0
// BLUE == 4 (GREEN + 1)
enum Color : uint32_t { RED, GREEN = 3, BLUE }

enum ยังสามารถสืบทอดจาก enum ที่กำหนดไว้ก่อนหน้านี้ได้ หากไม่มีการระบุค่าสำหรับตัวแจงนับตัวแรกของแจงนับลูก (ในกรณีนี้ FullSpectrumColor ) ค่าดีฟอลต์จะถูกระบุเป็นค่าของตัวแจงนับตัวสุดท้ายของแจงนับพาเรนต์บวกหนึ่ง ตัวอย่างเช่น:

// ULTRAVIOLET == 5 (Color:BLUE + 1)
enum FullSpectrumColor : Color { ULTRAVIOLET }

คำเตือน: การสืบทอด Enum ทำงานแบบย้อนกลับจากการสืบทอดประเภทอื่นๆ ส่วนใหญ่ ค่าแจงนับลูกไม่สามารถใช้เป็นค่าแจงนับพาเรนต์ได้ เนื่องจากแจงนับลูกมีค่ามากกว่าค่าพาเรนต์ อย่างไรก็ตาม ค่าแจงนับพาเรนต์สามารถใช้เป็นค่าแจงนับย่อยได้อย่างปลอดภัย เนื่องจากค่าแจงนับย่อยคือค่าซูเปอร์เซ็ตของค่าแจงนับพาเรนต์ตามคำนิยาม โปรดคำนึงถึงสิ่งนี้เมื่อออกแบบอินเทอร์เฟซ เนื่องจากหมายความว่าประเภทที่อ้างถึงการแจงนับพาเรนต์จะไม่สามารถอ้างถึงแจงย่อยย่อยในการวนซ้ำอินเทอร์เฟซของคุณในภายหลัง

ค่าของแจงนับจะอ้างอิงตามไวยากรณ์โคลอน (ไม่ใช่ไวยากรณ์จุดเป็นประเภทที่ซ้อนกัน) ไวยากรณ์คือ Type:VALUE_NAME ไม่จำเป็นต้องระบุประเภทหากมีการอ้างอิงค่าในประเภทแจงนับหรือประเภทลูกเดียวกัน ตัวอย่าง:

enum Grayscale : uint32_t { BLACK = 0, WHITE = BLACK + 1 };
enum Color : Grayscale { RED = WHITE + 1 };
enum Unrelated : uint32_t { FOO = Color:RED + 1 };

เริ่มต้นใน Android 10 enums มีแอตทริบิวต์ len ที่สามารถใช้ในนิพจน์คงที่ได้ MyEnum::len คือจำนวนรายการทั้งหมดในการแจงนับนั้น ซึ่งแตกต่างจากจำนวนค่าทั้งหมดซึ่งอาจน้อยกว่าเมื่อมีการทำซ้ำค่า

โครงสร้าง

HIDL ไม่รองรับโครงสร้างที่ไม่ระบุชื่อ มิฉะนั้น โครงสร้างใน HIDL จะคล้ายกับ C มาก

HIDL ไม่รองรับโครงสร้างข้อมูลที่มีความยาวผันแปรได้ซึ่งอยู่ภายในโครงสร้างทั้งหมด ซึ่งรวมถึงอาร์เรย์ที่มีความยาวไม่จำกัดซึ่งบางครั้งใช้เป็นฟิลด์สุดท้ายของโครงสร้างใน C/C++ (บางครั้งเห็นด้วยขนาด [0] ) HIDL vec<T> แสดงถึงอาร์เรย์ขนาดไดนามิกพร้อมข้อมูลที่จัดเก็บไว้ในบัฟเฟอร์แยกต่างหาก กรณีดังกล่าวจะแสดงด้วยอินสแตนซ์ของ vec<T> ใน struct

ในทำนองเดียวกัน string สามารถอยู่ใน struct ได้ (บัฟเฟอร์ที่เกี่ยวข้องจะแยกจากกัน) ใน C ++ ที่สร้างขึ้น อินสแตนซ์ของประเภทตัวจัดการ HIDL จะแสดงผ่านตัวชี้ไปยังตัวจัดการดั้งเดิมจริง เนื่องจากอินสแตนซ์ของชนิดข้อมูลพื้นฐานมีความยาวผันแปรได้

ยูเนี่ยน

HIDL ไม่สนับสนุนสหภาพที่ไม่ระบุชื่อ มิฉะนั้นสหภาพแรงงานจะคล้ายกับ C.

ยูเนี่ยนไม่สามารถมีประเภทการแก้ไขได้ (พอยน์เตอร์, ตัวอธิบายไฟล์, อ็อบเจ็กต์เครื่องผูก ฯลฯ) ไม่จำเป็นต้องมีช่องพิเศษหรือประเภทที่เกี่ยวข้อง และเพียงคัดลอกผ่าน memcpy() หรือเทียบเท่า ยูเนี่ยนอาจไม่มีโดยตรง (หรือประกอบด้วยผ่านโครงสร้างข้อมูลอื่น) สิ่งใด ๆ ที่ต้องตั้งค่าออฟเซ็ตเครื่องผูก (เช่น การอ้างอิงหมายเลขอ้างอิงหรืออินเทอร์เฟซเครื่องผูก) ตัวอย่างเช่น:

union UnionType {
uint32_t a;
//  vec<uint32_t> r;  // Error: can't contain a vec<T>
uint8_t b;1
};
fun8(UnionType info); // Legal

สหภาพยังสามารถประกาศภายในโครงสร้างได้ ตัวอย่างเช่น:

struct MyStruct {
    union MyUnion {
      uint32_t a;
      uint8_t b;
    }; // declares type but not member

    union MyUnion2 {
      uint32_t a;
      uint8_t b;
    } data; // declares type but not member
  }