C++中sizeof运算符全面详解和代码示例
作者:点云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); - 显示结构体整体
sizeof和alignof; - 兼容 GCC / Clang / MSVC;
- 可用于诊断因字节对齐(padding)带来的内存浪费。
工具类:StructInspector
功能说明:
- 使用
offsetof获取成员偏移; - 使用
sizeof和alignof获取结构体大小和对齐; - 可扩展支持任意结构体(通过宏注册成员)。
示例代码
#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运算符内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
