gpt4 book ai didi

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

转载 作者:可可西里 更新时间:2023-11-01 16:31:19 26 4
gpt4 key购买 nike

当我回答问题时才 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;

我的问题是我是否做 Actor intStruct* structPtr = (intStruct*) intPtr;
如果我遍历结构体的元素,我确定能正确获取每个元素吗?在任何架构/编译器中是否存在未对齐(可能由于填充)的可能性?

最佳答案

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

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

An object of trivially copyable or standard-layout type (3.9) shall occupy contiguous bytes of storage."



...用于数组的那些(第 8.3.4/1 节):

An object of array type contains a contiguously allocated non-empty set of N subobjects of type T.



在数组中,元素本身需要连续分配,而在结构中,只需要存储是连续的。

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

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

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

在您的情况下,您有一个 POD 结构,因此(第 9.2/17 节):“指向 POD 结构对象的指针,使用 reinterpret_cast 进行适当转换,指向其初始成员(或者如果该成员是位域,然后到它所在的单位),反之亦然。”由于第一个成员必须对齐,而其余成员都是相同的类型,因此其他成员之间不可能真正需要任何填充(即,除了位域,您可以将任何类型放入结构中)也可以放入需要连续分配元素的数组中)。如果您的元素小于单词,则在面向单词的机器(例如,早期的 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 )。因此,您的四个结构 int s,您可能希望在元素之间看到另外 32 位的填充(以及最后一个元素之后的另外 32 位)。

鉴于您确实有一个 POD 结构,但您仍然有一些可能性。我可能更喜欢使用 offsetof获取结构成员的偏移量,创建它们的数组,并通过这些偏移量访问成员。我在 couple 中展示了如何做到这一点的 previous answers .

关于c++ - 将原始类型指针转换为结构指针 - 对齐和填充?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12138243/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com