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

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

ความคล้ายคลึงกันกับ C++ ได้แก่

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

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

  • แต่ละไฟล์ HIDL จะกำหนดเนมสเปซแบบ Java ซึ่งต้องขึ้นต้นด้วย android.hardware. เนมสเปซของ C++ ที่สร้างขึ้นคือ ::android::hardware::…
  • คำจำกัดความทั้งหมดของไฟล์จะอยู่ในรูปแบบ Java Wrapper interface
  • การประกาศอาร์เรย์ 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 arrays จะจับคู่กับอาร์เรย์ 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…) โดยที่ค่าอาจเป็นนิพจน์คงที่ สตริง หรือรายการค่า ภายใน {} เช่นเดียวกับใน Java คำอธิบายประกอบหลายรายการที่มีชื่อเดียวกัน สามารถแนบกับรายการเดียวกันได้

ประกาศส่งต่อ

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

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

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

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

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 มีการใช้งาน 2 อย่าง

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

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

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

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

คุณสามารถส่งอินเทอร์เฟซได้ 2 วิธีเท่านั้น ได้แก่ ส่งเป็นพารามิเตอร์ระดับบนสุด หรือส่งเป็น สมาชิกของ vec<IMyInterface> พวกเขาต้องไม่เป็นสมาชิกของ vecs, structs, อาร์เรย์ หรือยูเนียนที่ฝังอยู่

MQDescriptorSync และ MQDescriptorUnsync

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

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

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

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

ประเภทเคอร์เซอร์

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

บิตฟิลด์<T> พิมพ์เทมเพลต

bitfield<T> โดยที่ T เป็น enum ที่ผู้ใช้กำหนดแนะนำว่าค่านี้เป็นบิตไวส์หรือของค่า ค่า 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);

คอมไพเลอร์จะจัดการการแฟล็กประเภทเดียวกับ uint8_t

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

แฮนเดิลประเภทพื้นฐาน

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

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

แฮนเดิลเนทีฟ

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;

แฮนเดิลเนทีฟคือคอลเล็กชันของ int และข้อบ่งชี้ไฟล์ที่ส่งผ่าน รอบๆ ตามค่า คุณจัดเก็บข้อบ่งชี้ไฟล์เดียวในแฮนเดิลที่มาพร้อมเครื่องได้ ไม่มี Ints และข้อบ่งชี้ไฟล์เดียว การส่งแฮนเดิลโดยใช้แฮนเดิลเนทีฟ ห่อหุ้มด้วยประเภท handle แบบพื้นฐานจะช่วยให้แน่ใจว่าโฆษณาเนทีฟ แฮนเดิลจะรวมอยู่ใน HIDL โดยตรง

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

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

แฮนเดิลและการเป็นเจ้าของข้อบ่งชี้ไฟล์

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

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

HIDL ไม่รองรับแฮนเดิลใน Java (เนื่องจาก Java ไม่รองรับแฮนเดิลที่ ทั้งหมด)

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

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

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

เครื่องสาย

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

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

เวค<T> พิมพ์เทมเพลต

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

T อาจเป็นอย่างใดอย่างหนึ่งต่อไปนี้

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

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

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

แจกแจง

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

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

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

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

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

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

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

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

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 เป็นต้นไป Enum จะมี len ที่ใช้ในนิพจน์คงที่ได้ MyEnum::len คือจำนวนรายการทั้งหมดในการแจกแจงนั้น ซึ่งแตกต่างจากจำนวนค่าทั้งหมด ซึ่งอาจน้อยกว่าเมื่อ มีค่าซ้ำกัน

โครงสร้าง

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

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

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

Union

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

สหภาพต้องไม่มีประเภทการแก้ไข (เช่น ตัวชี้ ข้อบ่งชี้ไฟล์ ไฟล์ Binder ) แต่ไม่จำเป็นต้องมีฟิลด์พิเศษหรือประเภทที่เกี่ยวข้อง และ เพียงคัดลอกโดยใช้ 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
  }