将原始类型指针转换为结构指针 - 对齐和填充?

2024-01-26

就在我回答问题 20 分钟的时候,我想到了一个有趣的场景,但我不确定其行为:

让我有一个大小为 n 的整数数组,由 intPtr 指向;

int* intPtr;

让我也有一个这样的结构:

typedef struct {
int val1;
int val2;
//and less or more integer declarations goes on like this(not any other type)
}intStruct;

我的问题是我是否进行演员阵容intStruct* structPtr = (intStruct*) intPtr;

如果我遍历结构体的元素,我是否能正确获取每个元素?在任何架构/编译器中是否存在未对齐的可能性(可能是由于填充)?


该标准相当具体,即使是 POD 结构(我认为这是最严格的结构类)也可以在成员之间进行填充。 (“因此,POD 结构对象内可能有未命名的填充,但不是在其开头,这是实现适当对齐所必需的。”——非规范注释,但仍然使意图非常明确)。

例如,对比标准布局结构的要求(C++11,§1.8/4):

普通可复制或标准布局类型(3.9)的对象应占用连续的存储字节。”

...对于数组(§8.3.4/1):

数组类型的对象包含连续分配的 N 个类型为 T 的子对象的非空集合。

在数组中,elements它们本身需要连续分配,而在结构体中,只有storage要求是连续的。

可能使“连续存储”要求更有意义的第三种可能性是考虑不可简单复制或标准布局的结构/类。在这种情况下,存储可能根本不连续。例如,一种实现可能会留出一个内存区域来保存所有私有变量,并留出一个完全独立的内存区域来保存所有公共变量。为了使这一点更加具体,请考虑两个定义,例如:

class A { 
    int a;
public:
    int b;
} a;

class B {
    int x;
public:
    int y;
} b;

通过这些定义,内存的布局可能类似于:

a.a;
b.x;

// ... somewhere else in memory entirely:

a.b;
b.y;

在这种情况下,两个元素都没有nor存储需要是连续的,因此完全独立的结构/类的交错部分是允许的。

也就是说,第一个元素必须与整个结构位于同一地址 (9.2/17):“指向 POD 结构对象的指针,使用 reinterpret_cast 进行适当转换,指向其初始成员(或者如果该成员是一个位字段,然后是它所在的单元),反之亦然。”

在您的情况下,您有一个 POD 结构,因此(§9.2/17):“指向 POD 结构对象的指针,使用 reinterpret_cast 进行适当转换,指向其初始成员(或者如果该成员是位字段) ,然后到其所在的单位),反之亦然。”从第一个成员开始must对齐,并且其余成员都是相同类型,因此其他成员之间不可能真正需要任何填充(即,除了位字段之外,您可以放入结构中的任何类型也可以放入数组,其中需要连续分配元素)。如果您的元素小于单词,那么在面向单词的机器(例如早期的 DEC Alphas)上,填充可能会使访问变得更简单。例如,早期的 DEC Alpha(在硬件级别)一次只能读/写一个完整的(64 位)字。因此,让我们考虑一个由四个组成的结构char要素:

struct foo { 
   char a, b, c, d;
};

如果需要将它们放在内存中以便它们是连续的,则访问foo::b(例如)需要 CPU 加载该字,然后将其右移 8 位,然后掩码对该字节进行零扩展以填充整个寄存器。

存储会更糟 - CPU 必须加载整个字的当前值,屏蔽掉相应字符大小部分的当前内容,将新值移动到正确的位置,或者将其放入字中,最后存储结果。

相比之下,通过元素之间的填充,每个元素都变成简单的加载/存储,没有移位、屏蔽等。

至少如果没记错的话,使用 DEC 的 Alpha 正常编译器,int是 32 位,并且long是 64 位(早于long long)。因此,用你的四个结构ints,您可能会期望在元素之间看到另外 32 位的填充(以及最后一个元素之后的另外 32 位)。

鉴于您确实有 POD 结构,但您仍然有一些可能性。我可能更喜欢使用offsetof要获取结构体成员的偏移量,请创建它们的数组,并通过这些偏移量访问成员。我展示了如何在couple https://stackoverflow.com/a/5088496/179910 of 以前的答案 https://stackoverflow.com/a/2043949/179910.

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

将原始类型指针转换为结构指针 - 对齐和填充? 的相关文章

  • 编译时运算符

    有人可以列出 C 中可用的所有编译时运算符吗 C 中有两个运算符 无论操作数如何 它们的结果始终可以在编译时确定 它们是sizeof 1 and 2 当然 其他运算符的许多特殊用途可以在编译时解决 例如标准中列出的那些整数常量表达式 1 与
  • EF Core Group By 翻译支持条件总和

    听说 EF Core 2 1 将支持翻译小组 我感到非常兴奋 我下载了预览版并开始测试它 但发现我在很多地方仍然没有得到翻译分组 在下面的代码片段中 对 TotalFlagCases 的查询将阻止翻译分组工作 无论如何 我可以重写这个以便我
  • C 编程 - 文件 - fwrite

    我有一个关于编程和文件的问题 while current NULL if current gt Id Doctor 0 current current gt next id doc current gt Id Doctor if curre
  • 通过 CMIS (dotCMIS) 连接到 SP2010:异常未经授权

    我正在使用 dotCMIS 并且想要简单连接到我的 SP2010 服务器 我尝试用 C 来做到这一点 如下所示http chemistry apache org dotnet getting started with dotcmis htm
  • Web 客户端和 Expect100Continue

    使用 WebClient C NET 时设置 Expect100Continue 的最佳方法是什么 我有下面的代码 我仍然在标题中看到 100 continue 愚蠢的 apache 仍然抱怨 505 错误 string url http
  • ASP.NET MVC:这个业务逻辑应该放在哪里?

    我正在开发我的第一个真正的 MVC 应用程序 并尝试遵循一般的 OOP 最佳实践 我正在将控制器中的一些简单业务逻辑重构到我的域模型中 我最近一直在阅读一些内容 很明显我应该将逻辑放在域模型实体类中的某个位置 以避免出现 贫血域模型 反模式
  • 用于检查类是否具有运算符/成员的 C++ 类型特征[重复]

    这个问题在这里已经有答案了 可能的重复 是否可以编写一个 C 模板来检查函数是否存在 https stackoverflow com questions 257288 is it possible to write a c template
  • 查找c中结构元素的偏移量

    struct a struct b int i float j x struct c int k float l y z 谁能解释一下如何找到偏移量int k这样我们就可以找到地址int i Use offsetof 找到从开始处的偏移量z
  • 类模板参数推导 - clang 和 gcc 不同

    下面的代码使用 gcc 编译 但不使用 clang 编译 https godbolt org z ttqGuL template
  • C# 中通过 Process.Kill() 终止的进程的退出代码

    如果在我的 C 应用程序中 我正在创建一个可以正常终止或开始行为异常的子进程 在这种情况下 我通过调用 Process Kill 来终止它 但是 我想知道该进程是否已退出通常情况下 我知道我可以获得终止进程的错误代码 但是正常的退出代码是什
  • 创建链表而不将节点声明为指针

    我已经在谷歌和一些教科书上搜索了很长一段时间 我似乎无法理解为什么在构建链表时 节点需要是指针 例如 如果我有一个节点定义为 typedef struct Node int value struct Node next Node 为什么为了
  • while 循环中的 scanf

    在这段代码中 scanf只工作一次 我究竟做错了什么 include
  • 如何在整个 ASP .NET MVC 应用程序中需要授权

    我创建的应用程序中 除了启用登录的操作之外的每个操作都应该超出未登录用户的限制 我应该添加 Authorize 每个班级标题前的注释 像这儿 namespace WebApplication2 Controllers Authorize p
  • 如何在 C 中调用采用匿名结构的函数?

    如何在 C 中调用采用匿名结构的函数 比如这个函数 void func struct int x p printf i n p x 当提供原型的函数声明在范围内时 调用该函数的参数必须具有与原型中声明的类型兼容的类型 其中 兼容 具有标准定
  • Windows 窗体:如果文本太长,请添加新行到标签

    我正在使用 C 有时 从网络服务返回的文本 我在标签中显示 太长 并且会在表单边缘被截断 如果标签不适合表单 是否有一种简单的方法可以在标签中添加换行符 Thanks 如果您将标签设置为autosize 它会随着您输入的任何文本自动增长 为
  • 覆盖子类中的字段或属性

    我有一个抽象基类 我想声明一个字段或属性 该字段或属性在从该父类继承的每个类中具有不同的值 我想在基类中定义它 以便我可以在基类方法中引用它 例如覆盖 ToString 来表示 此对象的类型为 property field 我有三种方法可以
  • 对现有视频添加水印

    我正在寻找一种用 C 在视频上加水印的方法 就像在上面写文字一样 图片或文字标签 我该怎么做 谢谢 您可以使用 Nreco 视频转换器 代码看起来像 NReco VideoConverter FFMpegConverter wrap new
  • 通过指向其基址的指针删除 POD 对象是否安全?

    事实上 我正在考虑那些微不足道的可破坏物体 而不仅仅是POD http en wikipedia org wiki Plain old data structure 我不确定 POD 是否可以有基类 当我读到这个解释时is triviall
  • 基于 OpenCV 边缘的物体检测 C++

    我有一个应用程序 我必须检测场景中某些项目的存在 这些项目可以旋转并稍微缩放 更大或更小 我尝试过使用关键点检测器 但它们不够快且不够准确 因此 我决定首先使用 Canny 或更快的边缘检测算法 检测模板和搜索区域中的边缘 然后匹配边缘以查
  • 如何在文本框中插入图像

    有没有办法在文本框中插入图像 我正在开发一个聊天应用程序 我想用图标图像更改值 等 但我找不到如何在文本框中插入图像 Thanks 如果您使用 RichTextBox 进行聊天 请查看Paste http msdn microsoft co

随机推荐