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

 更新时间:2025年07月31日 09:18:50   作者:点云SLAM  
sizeof是C++中的一个编译时运算符,用于获取对象或类型所占的字节数,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

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]) << "\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";
    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 PRINT_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 << "------------------------------\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运算符内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家! 

相关文章

  • C语言数据结构实现字符串分割的实例

    C语言数据结构实现字符串分割的实例

    这篇文章主要介绍了C语言数据结构实现字符串分割的实例的相关资料,希望通过本文能帮助到大家实现这样的功能,需要的朋友可以参考下
    2017-10-10
  • C语言容易被忽视的函数设计原则基础

    C语言容易被忽视的函数设计原则基础

    C语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言.那么C语言函数设计的一般原则和技巧都是怎样的呢,下面带你了解
    2022-04-04
  • 帮VS2019 找回丢失的 SDK问题

    帮VS2019 找回丢失的 SDK问题

    最近很多朋友向小编求助在机器上的 vs2019 编译 C++ 工程报错问题,今天小编给大家分享帮VS2019 找回丢失的 SDK问题,感兴趣的朋友一起看看吧
    2020-05-05
  • C++图解单向链表类模板和iterator迭代器类模版详解

    C++图解单向链表类模板和iterator迭代器类模版详解

    这篇文章主要为大家详细介绍了C++图解单向链表类模板和iterator迭代器类模版,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-02-02
  • 基于Turbo C(V2.0)编译错误信息的详细介绍

    基于Turbo C(V2.0)编译错误信息的详细介绍

    本篇文章对Turbo C(V2.0)编译的错误信息进行了详细的介绍。需要的朋友参考下
    2013-05-05
  • Qt读写ini文件的方法详解(含源码+注释)

    Qt读写ini文件的方法详解(含源码+注释)

    .ini文件是Initialization File的缩写,即初始化文件,下面这篇文章主要给大家介绍了关于Qt读写ini文件(含源码+注释)的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-10-10
  • C++笔记之std::future的用法小结

    C++笔记之std::future的用法小结

    std::future通常由某个Provider创建,与std::async一起使用,本文主要介绍了C++笔记之std::future的用法小结,具有一定的参考价值,感兴趣的可以了解一下
    2023-10-10
  • C++扑克牌的洗牌发牌游戏设计

    C++扑克牌的洗牌发牌游戏设计

    这篇文章主要为大家详细介绍了C++扑克牌的洗牌发牌游戏设计,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-08-08
  • Qt中QPixmap、QImage、QPicture、QBitmap四者区别详解

    Qt中QPixmap、QImage、QPicture、QBitmap四者区别详解

    Qt 提供了四个类来处理图像数据:QImage、QPixmap、QBitmap 和 QPicture,本文就详细的介绍一下四者区别,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • 详解C语言中strpbrk()函数的用法

    详解C语言中strpbrk()函数的用法

    这篇文章主要介绍了详解C语言中strpbrk()函数的用法,是C语言入门学习中的基础知识,需要的朋友可以参考下
    2015-08-08

最新评论