让我有一个大小为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;
我的问题是如果我做一个cast intStruct * structPtr =(intStruct *)intPtr;
解决方法
例如,对比标准布局结构的要求(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.
在数组中,元素本身需要连续分配,而在结构中,只有存储需要是连续的.
可能使“连续存储”要求更有意义的第三种可能性是考虑一个不是简单的可复制或标准布局的结构体/类.在这种情况下,存储可能根本不可能是连续的.例如,一个实现可能会放置一个用于保存所有私有变量的内存区域,以及一个完全独立的内存区域来保存所有公共变量.为了使这一点更具体,考虑两个定义,如:
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):“使用reinterpret_cast适当转换的指向POD-struct对象的指针指向其初始成员(或者如果该成员是一个位域,然后到它所在的单位),反之亦然.
在你的情况下,你有一个POD结构,所以(§9.2/ 17):“指向一个POD-struct对象的指针,使用reinterpret_cast适当地转换,指向它的初始成员(或者如果该成员是一个位字段,反之亦然.由于第一个成员必须对齐,而其余的成员都是相同的类型,因此在其他成员之间的填充是绝对必要的(即,除了位字段之外,你可以把任何类型放在一个结构体中)也可以放在一个数组中,其中需要连续分配元素).如果您的单词小于单词面向机器(例如早期DEC Alphas),那么填充可能会使访问变得更简单.例如,早期DEC Alphas(在硬件级别)只能一次读/写一个完整的(64位)字.因此,让我们考虑一下四个char元素的结构:
struct foo { char a,b,c,d; };
如果需要将它们放在内存中以使它们相邻,则访问foo :: b(例如)将要求cpu加载该字,然后将其移位8位,然后将其掩码为零扩展该字节填写整个注册表.
存储将更糟糕 – cpu将必须加载整个字的当前值,掩盖当前适当的字符大小的内容,将新值移动到正确的位置,或将其更改为字,最后存储结果.
相比之下,通过元素间的填充,这些元素中的每一个都成为简单的加载/存储,没有移位,掩蔽等.
至少如果内存服务,DEC的Alpha的正常编译器,int是32位,长度是64位(早于long long).因此,使用四个int的结构,您可以预期在元素之间再次看到32位的填充(以及最后一个元素之后的另外32位).
考虑到你有一个POD结构,你仍然有一些可能性.我可能会喜欢的是使用offsetof获取结构体的成员的偏移量,创建它们的数组,并通过这些偏移访问成员.我在previous answers的couple中展示了如何做到这一点.