开发者

C++中sizeof运算符全面详解和代码示例

目录
  • 1. 基本语法
  • 2. 返回值类型
  • 3. 示例代码一览
  • 4. 结构体对齐示例(含填充字节)
  • 5. 指针和数组的区别
  • 6. 类的sizeof示例(含虚函数、继承)
  • 7. 注意事项
  • 8.sizeof与模板配合(常用于静态断言)
  • 9. C++11 起的alignof
  • 10、综合示例
    • 工具类:StructInspector
    • 示例代码
    • 示例输出(linux + GCC)
    • 可扩展功能
    • 小结
  • 总结

    sizeof 是 C++ 中的一个编译时运算符,用于获取对象或类型所占的字节数(以 size_t 返回)。它是掌握底层内存模型、结构体对齐、数组大小计算等的重要工具。

    1. 基本语法

    sizeof(type)      // 获取类型的大小
    sizeof expression // 获取表达式结果的大小
    

    2. 返回值类型

    • sizeof 返回类型是 std::size_t(定义在 <cstddef> 中),是一个无符号整型,足以容纳系统中对象的最大可能大小。

    3. 示例代码一览

    #include <IOStream>
    #include <cstddef>
    
    int main() {
        int a = 5;
        double b = 3.14;
        int arr[10];
    
        std::cout << "sizeof(int): " << sizeof(int) << "\n";
        std::cout << "sizeof(a): " << sizeof(a) << "\n";
        std::cout << "sizeof(b): " << sizeof b << "\n";  // 可省略括号
        std::cout << "sizeof(arr): " << sizeof(arr) << "\n";
        std::cout << "Number of elements in arr: " << sizeof(arr) / sizeof(arr[0]android) << "\n";
    
        return 0;
    }
    

    4. 结构体对齐示例(含填充字节)

    #include <iostream>
    
    struct A {
        char c;     // 1 byte
        int i;      // 4 bytes
    };
    
    int main() {
        std::cout << "sizeof(char): " << sizeof(char) << "\n";
        std::cout << "sizeof(int): " << sizeof(int) << "\n";
        std::cout << "sizeof(A): " << sizeof(A) << "\n";  // likely 8 due to padding
    }
    

    结构体 A 实际大小常常为 8,而不是 5,这是因为编译器插入了填充字节以保证成员变量对齐(称为结构体对齐或 padding)。

    5. 指针和数组的区别

    int arr[10];
    int* p = arr;
    
    std::cout << "sizeof(arr): " << sizeof(arr) << "\n";     // 10 * sizeof(int)
    std::cout << "sizeof(p): " << sizeof(p) << "\n";         // 指针大小,通常是 8(64 位系统)
    

    6. 类的sizeof示例(含虚函数、继承)

    #include <iostream>
    
    class Base {
        virtual void foo() {}
    };
    
    class Derived : public Base {
        int data;
    };
    
    int main() {
        std::cout << "sizeof(Base): " << sizeof(Base) << "\n";      // 有 vptr,通常为 8
        std::cout << "sizeof(Derived): " << sizeof(Derived) << "\n"; // vptr + int + padding
    }
    

    7. 注意事项

    事项说明
    sizeof 是编译时运算除非作用于 VLA(C99 风格,C++ 不支持),否则计算在编译期完成
    对于类型无需括号sizeof expression 中括号可省;sizeof(type) 中必须加括号
    数组退化sizeof(arr) 在函数参数中为指针大小,不是数组总大小
    对动态分配数组无效sizeof(new int[10]) 得到的是指针大小,不是数组大小

    8.sizeof与模板配合(常用于静态断言)

    template<typename T>
    void check_size() {
        static_assert(sizeof(T) <= 8, "Type is too big!");
    }
    

    9. C++11 起的alignof

    #include <iostream>
    #include <type_traits>
    
    struct MyStruct {
        char c;
        double d;
    };
    
    int main() {
        std::cout << "sizeof(MyStruct): " << sizeof(MyStruct) << "\n";
      http://www.devze.com  std::cout << "alignof(MyStruct): " << alignof(MyStruct) << "\n";
    }
    

    10、综合示例

    下面是一个 跨平台结构体对齐测试工具类 的完整示例,功能如下:

    • 显示结构体每个成员的偏移量(offsetof);
    • 显示结构体整体 sizeofalignof
    • 兼容 GCC / Clang / MSVC;
    • 可用于诊断因字节对齐(padding)带来的内存浪费。

    工具类:StructInspector

    功能说明:

    • 使用 offsetof 获取成员偏移;
    • 使用 sizeofalignof 获取结构体大小和对齐;
    • 可扩展支持任意结构体(通过宏注册成员)。

    示例代码

    #include <iostream>
    #include <iomanip>
    #include <cstddef>
    #include <string>
    #include <type_traits>
    
    // 通用格式输出宏
    #define PRIandroidNT_ALIGN_INFO(T) \
        std::cout << "Struct: " << #T << "\n" \
                  << "  Size:    " << sizeof(T) << "\n" \
                  << "  Alignof: " << alignof(T) << "\n\n";
    
    // 检查偏移宏(成员名必须为字符串形式)
    #define PRINT_MEMBER_OFFSET(StructType, Member) \
        std::cout << std::setw(20) << #Member << " @ offset: " << offsetof(StructType, Member) << "\n";
    
    
    // -----------------------------
    // 示例结构体
    // -----------------------------
    struct MyStruct {
        char    c1;
        double  d;
        int     i;
        char    c2;
    };
    
    struct PackedStruct {
        char c1;
        char c2;
        int  i;
    } __attribute__((packed));  // GCC/Clang 特性(MSVC: use #pragma pack)
    
    #pragma pack(push, 1)
    struct MsvcPackedStruct {
        char c1;
        char c2;
        int i;
    };
    #pragma pack(pop)
    
    
    // -----------------------------
    // 工具函数:打印结构体布局
    // -----------------------------
    template<typename T>
    void InspectStructLayout(const std::string& name) {
        std::cout << "==============================\n";
        std::cout << "Inspecting: " << name << "\n";
        std::cout << "sizeof(" << name << ") = " << sizeof(T) << "\n";
        std::cout << "alignof(" << name << ") = " << alignof(T) << "\n";
        std::cout << "------------www.devze.com------------------\n";
    }
    
    // 示例专用模板:打印具体成员偏移
    void Inspect_MyStruct() {
        InspectStructLayout<MyStruct>("MyStruct");
    
        PRINT_MEMBER_OFFSET(MyStruct, c1);
        PRINT_MEMBER_OFFSET(MyStruct, d);
        PRINT_MEMBER_OFFSET(MyStruct, i);
        PRINT_MEMBER_OFFSET(MyStruct, c2);
    
        std::cout << "\n";
    }
    
    void Inspect_PackedStruct() {
        InspectStructLayout<PackedStruct>("PackedStruct");
    
        PRINT_MEMBER_OFFSET(PackedStruct, c1);
        PRINT_MEMBER_OFFSET(PackedStruct, c2);
        PRINT_MEMBER_OFFSET(PackedStruct, i);
    
        std::cout << "\n";
    }
    
    void Inspect_MsvcPackedStruct() {
        InspectStructLayout<MsvcPackedStruct>("MsvcPackedStruct");
    
        PRINT_MEMBER_OFFSET(MsvcPackedStruct, c1);
        PRINT_MEMBER_OFFSET(MsvcPackedStruct, c2);
        PRINT_MEMBER_OFFSET(MsvcPackedStruct, i);
    
        std::cout << "\n";
    }
    
    // -----------------------------
    // 主程序入口
    // -----------------------------
    int main() {
        Inspect_MyStruct();
        Inspect_PackedStruct();
        Inspect_MsvcPackedStruct();
        return 0;
    }
    

    示例输出(Linux + GCC)

    ==============================
    Inspecting: MyStruct
    sizeof(MyStruct) = 24
    alignof(MyStruct) = 8
    ------------------------------
                     c1 @ offset: 0
                      d @ offset: 8
                      i @ offset: 16
                     c2 @ offset: 20
    
    ==============================
    Inspecting: PackedStruct
    sizeof(PackedStruct) = 6
    alignof(PackedStruct) = 1
    ------------------------------
                     c1 @ offset: 0
                     c2 @ offset: 1
                      i @ offset: 2
    
    ==============================
    Inspecting: MsvcPackedStruct
    sizeof(MsvcPackedStruct) = 6
    alignof(MsvcPackedStruct) = 1
    ------------------------------
                     c1 @ offset: 0
                     c2 @ offset: 1
                      i @ offset: 2
    

    可扩展功能

    可以封装为模板工具类,如下:

    template<typename T>
    struct StructAnalyzer {
        static void inspect(const std::vector<std::string>& member_names, const std::vector<std::size_t>& member_offsets) {
            std::cout << "Sizeof: " << sizeof(T) << ", Alignof: " << alignof(T) << "\n";
            for (size_t i = 0; i < member_names.size(); ++i)
                std::cout << member_names[i] << " @ offset: " << member_offsets[i] << 编程客栈"\n";
        }
    };
    

    因为 C++ 不支持反射,需要手动提供成员名与偏移。

    小结

    功能实现
    成员偏移计算offsetof(StructType, member)
    结构体大小与对齐sizeof, alignof
    跨平台结构体分析支持__attribute__((packed)) / #pragma pack(1)
    填充字节检查(诊断浪费)offsetof + sizeof 分析对比

    总结

    用法说明
    sizeof(type)获取某个类型的大小
    sizeof(expr)获取表达式类型的大小
    获取数组元素个数sizeof(arr) / sizeof(arr[0])
    获取结构体大小(含对齐)sizeof(Struct)
    与模板、static_assert 配合编译时类型检查
    指针大小与指向对象大小无关

    到此这篇关于C++中sizeof运算符全面详解和代码示例的文章就介绍到这了,更多相关C++ sizeof运算符内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)! 

    0

    上一篇:

    下一篇:

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    最新开发

    开发排行榜