C#中sizeof的用法详解:原理与内存对齐

半杯拿铁
半杯拿铁
发布时间:2026-10-14| 2人浏览过
原创

在C#开发中,计算数据类型的大小时,`sizeof`是一个常用的操作符,但其使用受到严格限制。本文将结合实际代码示例,分析`sizeof`的运行环境要求(unsafe)、适用对象(值类型),以及因内存对齐产生的大小偏差问题,并给出使用`StructLayout`进行精确控制的解决方案。

sizeof的基础应用与环境配置

在C#语言规范中,`sizeof`关键字的主要功能是获取特定类型在内存中所占用的字节数。由于它直接操作内存布局,属于底层操作范畴,因此在默认的安全模式下是无法直接使用的。

第1步:尝试使用sizeof并观察报错

首先定义一个引用类型(类),并在程序主逻辑中尝试调用:

public class MyUglyClass
{
  public char myChar1;
  public int myInt;
  public char myChar2;
}

class Program
{
  static void Main(string[] args)
  {
    // 错误示范:sizeof 不支持引用类型的实时计算,且必须在 unsafe 环境下
    Console.WriteLine(sizeof(MyUglyClass)); 
  }
}

编译运行该段代码,通常会遇到如下两类报错:

  1. 必须使用 unsafe 关键字:这表明当前代码处于非安全上下文,无法执行此类指针或内存级操作。
  2. 仅适用于值类型:如果将上述类替换为变量进行 sizeof 运算,还会提示该运算符不能作用于运行时分配的引用对象。

对应的编译错误界面如下图所示:
C#中使用sizeof引发的编译错误示意

第2步:开启Unsafe环境支持

要解决第一类报错,需要将目标对象改为值类型(struct),并在项目中开启允许不安全代码的选项。

操作步骤:

  1. 在Visual Studio解决方案资源管理器中,右键点击项目名称。
  2. 选择“属性”,进入项目配置面板。
  3. 切换到“生成 (Build)”选项卡。
  4. 勾选底部的“允许不安全代码 (Allow unsafe code)”复选框。
  5. 保存更改后重新构建项目。

修改后的代码逻辑:

[StructLayout(LayoutKind.Auto)] // 后续章节会详细讲解此特性
public struct MyUglyClass
{
  public char myChar1;
  public int myInt;
  public char myChar2;
}

class Program
{
  static void Main(string[] args)
  {
    MyUglyClass m = new MyUglyClass();
    // ... 初始化字段 ...
    
    // 核心变更:必须在 unsafe 块内执行 sizeof
    unsafe 
    {
      Console.WriteLine(sizeof(MyUglyClass)); 
    }
  }
}

内存对齐现象与StructLayout修正

完成基础配置后,再次运行上述代码,控制台输出的结果并非开发者预期的 8,而是 12。这是C#结构体内存排列机制导致的典型现象。

为什么大小是12而不是8?

按理论计算:

  • char 类型占 2 字节。
  • int 类型占 4 字节。
  • 总计应为 2 + 2 + 4 = 8 字节。

但在实际栈内存分配中,为了提高CPU读取效率,系统会对结构体成员进行对齐排列 (Alignment)。具体规则是较小字节的变量要向最大字节变量的边界看齐,不足的部分会被自动填充(Padding)补齐。

本例中的内存分布如下:myChar1 占用前2个字节,紧接着为了对齐接下来的 myInt(4字节对齐),系统预留了2个空位,随后才是4字节的 myInt,最后是 myChar2。

图示内存对齐分布如下:
结构体内存字节填充示意图

红叉所示部分即为无意义的对齐填充数据,这导致了空间利用率下降。

如何精确控制内存大小?

若需要忽略默认的对齐填充,强制按照定义的顺序紧凑排列,可以使用System.Runtime.InteropServices命名空间下的 [StructLayout] 特性。

using System.Runtime.InteropServices;

// 显式指定布局模式为 Auto 或 Sequential
[StructLayout(LayoutKind.Sequential)] // 此处改为Sequential更符合紧凑排列预期
public struct MyUglyClass
{
  public char myChar1;
  public int myInt;
  public char myChar2;
}

当正确设置了结构布局参数后,重新编译运行,此时 sizeof 将返回符合理论的数值 8。这证明了通过特性标注可以消除多余的空隙,优化内存占用。

总结

在使用 sizeof 时,请务必牢记两个前提条件:一是目标类型必须是值类型(struct),二是整个表达式必须包裹在 unsafe 代码块中,并且项目需具备“允许不安全代码”的配置权限。此外,对于涉及网络传输或二进制序列化的场景,默认的内存对齐可能导致数据长度异常,此时应利用 StructLayout 特性手动干预布局策略。

以上就是C#中sizeof的详细使用方法与内存原理解析,更多关于C#结构体编程的资料请关注本站其它相关文章!

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。