MST

星途 面试题库

面试题:C++结构体与联合体在嵌套使用时的特性差异

当C++的结构体和联合体进行嵌套使用时,它们的内存布局、成员访问规则等方面会产生哪些不同的特性?请通过代码示例详细分析。
45.9万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

内存布局特性

  1. 结构体嵌套结构体 结构体中嵌套结构体时,其内存布局是按照成员定义的顺序依次排列。每个成员的偏移量是其对齐值的整数倍,整个结构体的大小是其最大对齐值成员大小的整数倍。
#include <iostream>
struct InnerStruct {
    int a;  // 4字节,对齐值4
    char b; // 1字节,对齐值1
};  // InnerStruct大小为8字节(4 + 4)

struct OuterStruct {
    InnerStruct inner; // 8字节,对齐值8
    double c; // 8字节,对齐值8
};  // OuterStruct大小为16字节(8 + 8)

int main() {
    std::cout << "Size of InnerStruct: " << sizeof(InnerStruct) << std::endl;
    std::cout << "Size of OuterStruct: " << sizeof(OuterStruct) << std::endl;
    return 0;
}
  1. 联合体嵌套结构体 联合体的所有成员共享同一块内存空间,其大小是最大成员的大小。当联合体中嵌套结构体时,联合体的大小以嵌套的结构体大小为基准(如果结构体是最大成员)。
#include <iostream>
struct InnerStruct {
    int a;  // 4字节,对齐值4
    char b; // 1字节,对齐值1
};  // InnerStruct大小为8字节(4 + 4)

union OuterUnion {
    InnerStruct inner; // 8字节
    double c; // 8字节
};  // OuterUnion大小为8字节

int main() {
    std::cout << "Size of InnerStruct: " << sizeof(InnerStruct) << std::endl;
    std::cout << "Size of OuterUnion: " << sizeof(OuterUnion) << std::endl;
    return 0;
}
  1. 结构体嵌套联合体 结构体中嵌套联合体时,联合体成员按照其自身对齐规则在结构体中分配内存,结构体大小计算依然遵循最大对齐值成员大小的整数倍规则。
#include <iostream>
union InnerUnion {
    int a;  // 4字节,对齐值4
    char b; // 1字节,对齐值1
};  // InnerUnion大小为4字节

struct OuterStruct {
    InnerUnion inner; // 4字节,对齐值4
    double c; // 8字节,对齐值8
};  // OuterStruct大小为16字节(4 + 12)

int main() {
    std::cout << "Size of InnerUnion: " << sizeof(InnerUnion) << std::endl;
    std::cout << "Size of OuterStruct: " << sizeof(OuterStruct) << std::endl;
    return 0;
}
  1. 联合体嵌套联合体 联合体嵌套联合体时,整体大小为最外层联合体中最大成员的大小。内层联合体成员共享外层联合体的内存空间。
#include <iostream>
union InnerUnion {
    int a;  // 4字节,对齐值4
    char b; // 1字节,对齐值1
};  // InnerUnion大小为4字节

union OuterUnion {
    InnerUnion inner; // 4字节
    double c; // 8字节
};  // OuterUnion大小为8字节

int main() {
    std::cout << "Size of InnerUnion: " << sizeof(InnerUnion) << std::endl;
    std::cout << "Size of OuterUnion: " << sizeof(OuterUnion) << std::endl;
    return 0;
}

成员访问规则特性

  1. 结构体嵌套结构体 通过外层结构体对象访问内层结构体成员,使用 . 运算符。
#include <iostream>
struct InnerStruct {
    int a;
    char b;
};

struct OuterStruct {
    InnerStruct inner;
    double c;
};

int main() {
    OuterStruct outer;
    outer.inner.a = 10;
    outer.inner.b = 'A';
    outer.c = 3.14;
    std::cout << "Inner a: " << outer.inner.a << ", Inner b: " << outer.inner.b << ", Outer c: " << outer.c << std::endl;
    return 0;
}
  1. 联合体嵌套结构体 由于联合体成员共享内存,在访问嵌套的结构体成员时,只有当前激活的成员是有效的。
#include <iostream>
struct InnerStruct {
    int a;
    char b;
};

union OuterUnion {
    InnerStruct inner;
    double c;
};

int main() {
    OuterUnion outer;
    outer.inner.a = 10;
    outer.inner.b = 'A';
    std::cout << "Inner a: " << outer.inner.a << ", Inner b: " << outer.inner.b << std::endl;
    outer.c = 3.14;
    // 此时访问outer.inner.a和outer.inner.b结果是未定义的,因为当前激活成员是c
    std::cout << "Outer c: " << outer.c << std::endl;
    return 0;
}
  1. 结构体嵌套联合体 通过结构体对象访问联合体成员,再访问联合体内部成员,使用 . 运算符。
#include <iostream>
union InnerUnion {
    int a;
    char b;
};

struct OuterStruct {
    InnerUnion inner;
    double c;
};

int main() {
    OuterStruct outer;
    outer.inner.a = 10;
    std::cout << "Inner a: " << outer.inner.a << std::endl;
    outer.c = 3.14;
    std::cout << "Outer c: " << outer.c << std::endl;
    return 0;
}
  1. 联合体嵌套联合体 同样因为共享内存,要注意当前激活的成员。访问方式类似,通过外层联合体对象访问内层联合体成员。
#include <iostream>
union InnerUnion {
    int a;
    char b;
};

union OuterUnion {
    InnerUnion inner;
    double c;
};

int main() {
    OuterUnion outer;
    outer.inner.a = 10;
    std::cout << "Inner a: " << outer.inner.a << std::endl;
    outer.c = 3.14;
    // 此时访问outer.inner.a和outer.inner.b结果是未定义的,因为当前激活成员是c
    std::cout << "Outer c: " << outer.c << std::endl;
    return 0;
}

综上所述,结构体嵌套和联合体嵌套在内存布局和成员访问规则上存在显著差异,结构体按顺序分配内存,成员可同时有效访问;联合体成员共享内存,同一时间只有一个成员有效。