C/C++ 中嵌套结构的尾随填充 - 有必要吗?

2024-03-15

这更多的是一个理论问题。 我熟悉填充和尾随填充的工作原理。

struct myStruct{
    uint32_t x;
    char*    p;
    char     c;
};

// myStruct layout will compile to
// x:       4 Bytes
// padding: 4 Bytes
// *p:      8 Bytes
// c:       1 Byte
// padding: 7 Bytes
// Total:   24 Bytes

之后需要填充x, 以便*p已对齐,并且后面需要有尾部填充c这样整个结构体的大小就可以被 8 整除(为了得到正确的步幅长度)。 但考虑这个例子:

struct A{
    uint64_t x;
    uint8_t  y;
};

struct B{
    struct A myStruct;
    uint32_t c;
};

// Based on all information I read on internet, and based on my tinkering
// with both GCC and Clang, the layout of struct B will look like:
// myStruct.x:       8 Bytes
// myStruct.y:       1 Byte
// myStruct.padding: 7 Bytes
// c:                4 Bytes
// padding:          4 Bytes
// total size:       24 Bytes
// total padding:    11 Bytes
// padding overhead: 45%

// my question is, why struct A does not get "inlined" into struct B,
// and therefore why the final layout of struct B does not look like this:
// myStruct.x:       8 Bytes
// myStruct.y:       1 Byte
// padding           3 Bytes
// c:                4 Bytes
// total size:       16 Bytes
// total padding:    3 Bytes
// padding overhead: 19%

两种布局都满足所有变量的对齐。两种布局具有相同的变量顺序。在两种布局中struct B具有正确的步长(可被 8 字节整除)。唯一不同的是(除了尺寸缩小了 33%)struct A布局 2 中没有正确的步幅长度,但这应该不重要,因为显然没有数组struct As.

我用 -O3 和 -g 在 GCC 中检查了这个布局,struct B有 24 字节。

我的问题是 - 是否有某种原因导致不应用此优化? C/C++ 中是否存在某些布局要求禁止这样做?或者我缺少一些编译标志吗?或者这是 ABI 的事情吗?

编辑: 回答了。

  1. 请参阅 @dbush 的答案,了解为什么编译器无法自行发出此布局。
  2. 以下代码示例使用 GCC 编译指示packed and aligned(按照@jaskij的建议)手动强制执行更优化的布局。结构体B_packed只有 16 字节而不是 24 字节(请注意,当存在结构数组时,此代码可能会导致问题/运行缓慢B_packed,请注意,不要盲目复制此代码):
struct __attribute__ ((__packed__)) A_packed{
    uint64_t x;
    uint8_t  y;
};

struct __attribute__ ((__packed__)) B_packed{
    struct A_packed myStruct;
    uint32_t c __attribute__ ((aligned(4)));
};

// Layout of B_packed will be
// myStruct.x:       8 Bytes
// myStruct.y:       1 Byte
// padding for c:    3 Bytes
// c:                4 Bytes
// total size:       16 Bytes
// total padding:    3 Bytes
// padding overhead: 19%

是否有某种原因导致不应用此优化

如果允许的话,则值sizeof(struct B)会很含糊。

假设你这样做了:

struct B b;
struct A a = { 1, 2 };
b.c = 0x12345678;
memcpy(&b.myStruct, &a, sizeof(struct A));

你会覆盖的价值b.c.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C/C++ 中嵌套结构的尾随填充 - 有必要吗? 的相关文章

  • 为什么使用abs()或fabs()而不是条件否定?

    在 C C 中 为什么要使用abs or fabs 不使用以下代码即可查找变量的绝对值 int absoluteValue value lt 0 value value 这与较低级别的指令较少有关吗 您提出的 有条件的abs 并不等于std
  • MEX 文件中的断言导致 Matlab 崩溃

    我正在使用mxAssert 宏定义为matrix h在我的 C 代码中 mex 可以完美编译 当我调用的 mex 代码中违反断言时 该断言不会导致我的程序崩溃 而是导致 Matlab 本身崩溃 我错过了什么吗 这是有意的行为吗 当我查看 M
  • 在 C++ 中分割大文件

    我正在尝试编写一个程序 该程序接受一个大文件 任何类型 并将其分成许多较小的 块 我想我已经有了基本的想法 但由于某种原因我无法创建超过 12 kb 的块大小 我知道谷歌等上有一些解决方案 但我更感兴趣的是了解这个限制的根源是什么 然后实际
  • 获取两个字符串之间的公共部分c# [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我需要的是获取两个单词之间的共同部分并获取差异 例子 场景1 word1 感言 word2 Test 将返回 公共部分Test 不同之
  • 通信对象 System.ServiceModel.Channels.ServiceChannel 不能用于通信

    通信对象System ServiceModel Channels ServiceChannel 无法用于通信 因为它处于故障状态 这个错误到底是什么意思 我该如何解决它 您收到此错误是因为您让服务器端发生 NET 异常 并且您没有捕获并处理
  • 使用实体框架从集合中删除项目

    我正在使用DDD 我有一个 Product 类 它是一个聚合根 public class Product IAggregateRoot public virtual ICollection
  • try-catch 中未处理的异常

    try list from XElement e in d Descendants wix File where e Attribute Name Value Contains temp Name e Parent Parent Attri
  • 转到 C# WPF 中的第一页

    我正在 WPF 中使用导航服务 为了导航到页面 我使用 this NavigationService Navigate new MyPage 为了返回我使用 this NavigationService GoBack 但是如何在不使用的情况
  • Xamarin Android:获取内存中的所有进程

    有没有办法读取所有进程 而不仅仅是正在运行的进程 如果我对 Android 的理解正确的话 一次只有一个进程在运行 其他所有进程都被冻结 后台进程被忽略 您可以使用以下代码片段获取当前正在运行的所有 Android 应用程序进程 Activ
  • 禁用 LINQ 上下文的所有延迟加载或强制预先加载

    我有一个文档生成器 目前包含约 200 个项目的查询 但完成后可能会超过 500 个 我最近注意到一些映射表示延迟加载 这给文档生成器带来了一个问题 因为它需要根据生成的文档来访问所有这些属性 虽然我知道DataLoadOptions可以指
  • 通过不同 DLL 或 EXE 中的指针或引用访问 STL 对象时发生访问冲突

    我在使用旧版 VC6 时遇到以下问题 我只是无法切换到现代编译器 因为我正在处理遗留代码库 http support microsoft com kb 172396 http support microsoft com kb 172396
  • C# using 语句、SQL 和 SqlConnection

    使用 using 语句 C SQL 可以吗 private static void CreateCommand string queryString string connectionString using SqlConnection c
  • UWP 无法在两个应用程序之间创建本地主机连接

    我正在尝试在两个 UWP 应用程序之间设置 TCP 连接 当服务器和客户端在同一个应用程序中运行时 它可以正常工作 但是 当我将服务器部分移动到一个应用程序并将客户端部分移动到另一个应用程序时 ConnectAsync 会引发异常 服务器未
  • Qt - 设置不可编辑的QComboBox的显示文本

    我想将 QComboBox 的文本设置为某些自定义文本 不在 QComboBox 的列表中 而不将此文本添加为 QComboBox 的项目 此行为可以在可编辑的 QComboBox 上实现QComboBox setEditText cons
  • 无法使用 Ninject 将依赖项注入到从 Angular 服务调用的 ASP.NET Web API 控制器中

    我将 Ninject 与 ASP NET MVC 4 一起使用 我正在使用存储库 并希望进行构造函数注入以将存储库传递给其中一个控制器 这是实现 StatTracker 接口的上下文对象 EntityFramework public cla
  • 内核开发和 C++ [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 从我know https stackoverflow com questions 580292 what languages are windo
  • Fluent NHibernate 日期时间 UTC

    我想创建一个流畅的 nhibernate 映射来通过以下方式映射 DateTime 字段 保存时 保存 UTC 值 读取时 调整为本地时区值 实现此映射的最佳方法是什么 就我个人而言 我会将日期存储在 UTC 格式的对象中 然后在读 写时在
  • 过度使用委托对性能来说是一个坏主意吗? [复制]

    这个问题在这里已经有答案了 考虑以下代码 if IsDebuggingEnabled instance Log GetDetailedDebugInfo GetDetailedDebugInfo 可能是一个昂贵的方法 因此我们只想在调试模式
  • 以编程方式使用自定义元素创建网格

    我正在尝试以编程方式创建一个网格 并将自定义控件作为子项附加到网格中 作为 2x2 矩阵中的第 0 行第 0 列 为了让事情变得更棘手 我使用了 MVVM 设计模式 下面是一些代码可以帮助大家理解这个想法 应用程序 xaml cs base
  • boost::program_options:带有固定和可变标记的参数?

    是否可以在 boost program options 中使用此类参数 program p1 123 p2 234 p3 345 p12 678 即 是否可以使用第一个标记指定参数名称 例如 p 后跟一个数字 是动态的吗 我想避免这种情况

随机推荐

  • GeoJson c# 示例解析世界上的国家并为每个国家生成Geojson

    寻找如何使用 geojson net 解析 反序列化 Geojson 文件的示例 由于某种原因 没有如何使用 geojson net 包的示例 我想在我的网站上使用它和 google 地图 api 目前我使用多边形形状 但希望转向使用 ge
  • Android 中文本行的垂直 fling 滚动

    我已经实现了 Android Note Pad 示例代码中的编辑器代码 现在我想添加垂直滚动文本行的功能 我想要完成的一个例子是 Andorid 中选项行的快速滚动 我在谷歌上搜索了滚动器和投掷的示例 但找不到任何适合我需要的东西 我还没有
  • 如何将 IP 地址和端口号作为 url 传递

    为了传递 url 我有 ip 地址和端口号 如何将其作为 http url 发送 ex ip address 10 5 90 948 port number as 71 http 10 5 90 948 71 这需要网址吗 如果不是 如何将
  • ASP.NET MVC 记住我

    我有一个基于 ASP NET MVC 4 的项目 可以进行简单的身份验证 我试图让我的网站在用户选中 记住我 复选框时自动登录 但是我在使其正常工作时遇到问题 关闭浏览器并重新打开后 用户永远不会登录 检查后 http forums asp
  • 了解 PHP 中的类

    我正式成为弱智 让我解释 直到今天我才真正考虑过类和它们之间的关系 我试图找出一些看起来很明显的东西 但由于我很愚蠢 所以我看不到它 假设我有一个将从不同文件扩展的核心类 子类如何调用其他兄弟类的函数 也就是说 如果这些类根本被视为子类 示
  • 不使用 com.sun.xml.internal.*?

    以下说法是否属实 com sun xml internal 包顾名思义是一个内部包 用户不应编写依赖于内部 JDK 实现类的代码 此类是 JDK 的内部实现细节 如有更改 恕不另行通知 我的一位同事在他的代码中使用了其中一个类 这导致 An
  • 检测点数组中的形状

    我有一系列的点 我想知道这个点数组是否代表圆形 正方形或三角形 我应该从哪里开始 我使用C 谢谢 乔恩 根据您的问题 解决此问题的一个好方法可能是使用霍夫变换 http en wikipedia org wiki Hough transfo
  • 如果第一个字符是 SQL 中的特定字符,如何删除它

    我目前有一张桌子Telephone它有如下条目 9073456789101 773456789101 0773456789101 我想要做的是只删除所有有 9 的条目开头的 9 但保留其他条目不变 任何帮助将不胜感激 虽然所有其他答案可能也
  • 仅使用代码保存networkD3桑基图

    我在 R 中创建了一个桑基图 使用networkD3包 我想使用代码保存为静态图像 而不是单击 导出 gt 另存为图像 我尝试过的当前代码 使用this https christophergandrud github io networkD
  • 您什么时候开始使用 HTML 5?

    所以 HTML 5 正如预期的那样被广泛宣传2022年准备就绪 http ishtml5readyyet com 这是一个很长的等待时间 而对准备情况的考验是 至少有两个浏览器能够完全通过 HTML 5 测试套件 显然 浏览器要通过此测试
  • Android 中的 Dom xml 解析

    我是android开发新手 我不知道如何从xml解析数据 所以请帮忙 这是我必须解析的 Xml
  • PerformFiltering() 期间发生 Android Realm 异常!

    当我使用 Spinner 时 该应用程序运行良好 但是 当我尝试使用 AutoComplete Textview 而不是 Spinner 时 我在其上键入内容时不会显示任何内容 任何帮助表示赞赏 Logcat 警告 08 23 14 01
  • 带有字符串的 String.raw 仅适用于不带括号的情况

    我知道您可以使用模板文字来提供方法的第一个参数 例如 const f x gt hello x f world returns hello world 所以我可以以某种方式理解为什么这段代码有效 String raw bla bla 但是
  • 创建无限循环

    我正在尝试创建一个无限循环 其中代码块将永远执行 我发现的所有循环文档都警告不要创建无限循环 但没有有效循环的示例 如果我有一段代码 puts foo puts bar sleep 300 我将如何永远运行这个块 loop do puts
  • Ruby on Rails,一种形式的两种模型

    我有两个非常相似的模型预处理和诊断 属于模型患者 class Pretreatment lt ActiveRecord Base belongs to patient attr accessible content end class Di
  • 设置 Asp:Chart 控件的动态大小

    我试图使我的图表宽度和高度动态化 但我无法让它工作 到目前为止我已经尝试过 我已将图表设置在 Asp Panel 内 并为面板提供了所需的百分比值
  • 在org-mode下,如何让代码块默认折叠?

    在 Emacs org mode 中 我如何指示 org mode 让 HTML 代码块默认折叠 那么当我打开一个 org 文件时它们会被折叠吗 org mode 提供了开箱即用的此功能 您可以通过自定义变量来全局设置它org hide b
  • ViewPagerIndicator中拦截触摸事件

    我正在使用杰克 沃顿的查看寻呼指示器 http viewpagerindicator com在我的 FragmentActivity 上 其中包含一个 viewpager 我在拦截 onTouch 事件时遇到困难 我知道 ViewPager
  • 如何向现有 Win32 C++ 项目添加 MFC 支持?

    我正在创建一个 C 应用程序 它使用 Qt 创建 GUI 但是 我需要使用依赖于 MFC 的第三方库 用于 CString 等 无论如何 是否可以将 MFC 添加到我的应用程序中以允许我使用这个库 或者我需要自己重写它 I saw 这个问题
  • C/C++ 中嵌套结构的尾随填充 - 有必要吗?

    这更多的是一个理论问题 我熟悉填充和尾随填充的工作原理 struct myStruct uint32 t x char p char c myStruct layout will compile to x 4 Bytes padding 4