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 byteint 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,通常为 8std::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: 0d @ offset: 8i @ offset: 16c2 @ offset: 20==============================
Inspecting: PackedStruct
sizeof(PackedStruct) = 6
alignof(PackedStruct) = 1
------------------------------c1 @ offset: 0c2 @ offset: 1i @ offset: 2==============================
Inspecting: MsvcPackedStruct
sizeof(MsvcPackedStruct) = 6
alignof(MsvcPackedStruct) = 1
------------------------------c1 @ offset: 0c2 @ offset: 1i @ 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 配合编译时类型检查
指针大小与指向对象大小无关

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/91291.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/91291.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/91291.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

内容中台:在一个地方管理多渠道内容

在数字化竞争愈演愈烈的今天&#xff0c;企业官网、社交平台、移动应用、邮件营销等渠道已成为品牌触达用户的关键接口。内容仍是连接企业与客户的核心资产。然而&#xff0c;内容创作与分发的复杂性持续攀升&#xff0c;多平台运营面临重复维护、更新不一致、资源冗余等诸多挑…

【刷题】东方博宜oj 1307 - 数的计数

样例输入&#xff1a; 6输出&#xff1a; 16 26 126 36 136原版是直接输出总数量&#xff0c;但我修改了一些&#xff0c;输出所有的新数。 #include <iostream> #include <vector> #include <string> using namespace std; //int c; void g(int num, string…

阿里云AI代码助手通义灵码开发指导

与阿里云一起轻松实现数智化让算力成为公共服务&#xff1a;用大规模的通用计算&#xff0c;帮助客户做从前不能做的事情&#xff0c;做从前做不到的规模。让数据成为生产资料&#xff1a;用数据的实时在线&#xff0c;帮助客户以数据为中心改变生产生活方式创造新的价值。智能…

设计模式(二十三)行为型:模板方法模式详解

设计模式&#xff08;二十三&#xff09;行为型&#xff1a;模板方法模式详解模板方法模式&#xff08;Template Method Pattern&#xff09;是 GoF 23 种设计模式中的行为型模式之一&#xff0c;其核心价值在于定义一个操作中的算法骨架&#xff0c;而将一些步骤延迟到子类中实…

Postgresql 查询使用正则

今天接到任务&#xff0c;要从数据库中查询数据&#xff0c;对于postgresql 我并不熟悉&#xff0c;问了百度&#xff0c;问了通义千问。发现Postgresql 在写query sql 的时候&#xff0c;可以使用正则匹配&#xff0c;不单是使用like 这种关键字。我像发现了新大陆一样的兴奋。…

【WRF-Chem Emissions教程第八期】转换实用程序

转换实用程序 8.1 将中间二进制文件转换为 WRF-Chem 数据文件 文件命名规范与风格 8.2 Binary data file format(中间二进制排放数据文件的格式和结构) FORTRAN 示例程序说明 8.3 Building the WRF-Chemistry emissions conversion code 编译步骤 验证编译结果 8.4 Namelist …

Qt Ribbon效果界面

实现效果&#xff1a;头文件&#xff1a;#pragma once #include <QMdiArea> #include <QMdiSubWindow> #include <QMainWindow> #include "ui_MainFrame1.h" #include "DockManager.h" #include "DockAreaWidget.h"class Main…

如何修改 MySQL 8.0 的密码,和忘记密码时如何修改

要修改 MySQL 8.0 的密码&#xff0c;可以通过以下几种方法实现&#xff1a;方法 1&#xff1a;使用 ALTER USER 命令&#xff08;推荐&#xff09;这是 MySQL 8.0 推荐的修改密码方式&#xff1a;-- 修改当前登录用户的密码 ALTER USER USER() IDENTIFIED BY 新密码;-- 修改指…

图像处理控件Aspose.Imaging教程:使用 C# 编程将 CMX 转换为 PNG

PNG图像文件格式是广泛使用的图像格式之一。这种图像文件格式提供了增强的共享和显示功能。另一方面&#xff0c;CMX也是 Corel 应用程序主要使用的图像文件格式。然而&#xff0c;将 CMX 转换为 PNG 可以帮助用户在网络上查看和共享文件。因此&#xff0c;在本指南中&#xff…

迪丽热巴写真壁纸

下载&#xff1a;https://pan.quark.cn/s/a740dbac8274迪丽热巴绝美写真&#xff0c;高清壁纸展现独特魅力&#xff0c;每一张都是视觉盛宴

C++11 std::function 详解:通用多态函数包装器

在C11标准中&#xff0c;引入了std::function这一通用多态函数包装器&#xff0c;定义于<functional>头文件中。它彻底改变了C中函数对象的使用方式&#xff0c;为不同类型的可调用实体提供了统一的接口。std::function能够存储、复制和调用任何可复制构造的可调用目标&a…

Kafka运维实战 16 - kafka 分区重新分配【实战】

💻 Kafka运维实战 (17篇) 📝Kafka运维实战 17 - kafka 分区副本从 1 增加到 3【实战】 📝Kafka运维实战 16 - kafka 分区重新分配【实战】 📝Kafka运维实战 15 - kafka 重设消费者组位移入门和实战【实战】 📝Kafka运维实战 14 - kafka消费者组消费进度(Lag)深入理…

智汇AI,应用领航 | 华宇万象问数入选2025全景赋能典型案例

7月29日&#xff0c;以“AI城市&#xff1a;数启新纪元”为主题中关村人工智能与未来城市论坛在中关村国家自主创新示范区展示中心举办。本次论坛围绕人工智能创新应用落地实践、新型数据基础设施建设、数据要素价值释放机制、城市智能治理等关键议题&#xff0c;邀请院士专家和…

sqli-labs:Less-7关卡详细解析

1. 思路&#x1f680; 本关的SQL语句为&#xff1a; $sql"SELECT * FROM users WHERE id(($id)) LIMIT 0,1";注入类型&#xff1a;字符串型&#xff08;单引号、双括号包裹&#xff09;提示&#xff1a;参数id需以))闭合 同样无法像常规一样回显&#xff0c;php输出语…

编程算法:从理论基石到产业变革的核心驱动力

文章目录 算法的本质与效率衡量 基础算法范式的实践价值 排序算法的演进与选择 动态规划的实用技巧 算法在现代技术栈中的应用 大数据处理的算法框架 编译器中的算法优化 算法驱动的产业变革 金融领域的算法应用 医疗健康领域的算法创新 制造业的算法优化 算法的未来趋势 结语 …

深度学习中的注意力机制:原理、应用与未来展望

在人工智能领域&#xff0c;深度学习技术已经取得了巨大的突破&#xff0c;而注意力机制&#xff08;Attention Mechanism&#xff09;作为深度学习中的一个重要概念&#xff0c;正在逐渐改变我们对模型的理解和应用。本文将深入探讨注意力机制的原理、在不同领域的应用以及未来…

LeetCode 4:寻找两个正序数组的中位数

LeetCode 4&#xff1a;寻找两个正序数组的中位数问题定义与核心挑战 给定两个有序&#xff08;升序&#xff09;数组 nums1 和 nums2&#xff0c;要求找到它们的中位数&#xff0c;且算法时间复杂度为 O(log(mn))&#xff08;m 和 n 分别是两个数组的长度&#xff09;。 中位数…

独立站如何吃掉平台蛋糕?DTC模式下的成本重构与利润跃升

一、成本结构革命&#xff1a;从「流量税」到「用户终身价值」亚马逊卖家需支付15%佣金12%广告费&#xff0c;导致每$100收入中平台抽成$27。而成熟独立站通过SEO&#xff08;自然流量占比超40%&#xff09;和社交媒体内容引流&#xff0c;将获客成本压缩至$8-$15。更关键的是用…

应用驱动 协同创新:中国人工智能开启高质量发展新篇章

人工智能技术的突破性发展正引发全球产业格局的深刻变革。在2025年这个关键节点&#xff0c;中国以"应用导向"为战略支点&#xff0c;依托新型举国体制优势&#xff0c;正在构建具有中国特色的人工智能发展体系&#xff0c;为全球智能革命贡献东方智慧。一、战略布局…

ZKMall商城开源本地部署指南

1. 开发环境配置 以下是开发工具的最低版本要求。在继续之前&#xff0c;请务必安装所有必需的依赖项。 工具版本JDK17MySQL5.7.3Redis5.0Maven3.9.5NodeJS20.18.0 1.1 安装资源 如需详细的安装指南&#xff0c;您可以参考以下教程&#xff1a; JDK: 菜鸟教程 Java 环境搭建…