是否保证C中的数组元素将连续存储,没有填充?

换句话说:如果我有这样分配的数组,它是否可以保证:

void *arr = calloc(nmemb, sizeof(some_type)) 

那么eltaeltbeltc都将指向内存中的相同位置,这将是此数组some_type类型的第二个元素?

 some_type *elta = &((some_type*)arr)[1]; some_type *eltb = ((some_type*)arr)+1; some_type *eltc = (char*)arr+sizeof(some_type); 

我问这个的原因是因为我试图在C中做一个“容器”,如果这不成立,那么我就没有想法如何返回指向除第一个之外的任何其他元素的指针。

是的,这是有保证的。 如果添加了填充字节,则它们将添加 struct some_type ,但不会添加两个数组元素之间。

E. g。:

 struct S { int n; short s; // this is just for illustration WHERE byte padding (typically) would occur!!! #if BYTE_ALIGNMENT >= 4 unsigned char : 0; unsigned char : 0; #endif }; struct S s[2]; size_t d = (char*)(s + 1) - (char*)s; 

将字节对齐调整为4或8(或更大的2的幂),此结构的大小为8,d将为8,字节对齐设置为1或2,结构的大小为6是……

注意:这不是唯一可以发生填充字节的地方:如果切换成员ns ,则在sn之间需要填充字节以使n正确对齐。 另一方面,在n之后不再需要填充字节,因为结构大小将确保已经正确对齐。

参考标准:C11,6.2.5.20:

数组类型描述了具有特定成员对象类型的连续分配的非空对象集,称为元素类型。 36)数组类型的特征在于它们的元素类型和数组中元素的数量。 […]

(突出显示我!)。

数据对齐是一个复杂的问题,如以下示例所示(您甚至可以绘制以进行自己的实验):

 #include  struct A { /* no padding */ char a[3]; }; struct B { int a; char b[3]; /* one byte of padding (in 32bit arch) added here */ }; struct C { /* no padding again */ char a[4]; char b[3]; }; struct D { char a[3]; /* one byte of padding to ensure alignment of next field */ int b; char c[3]; /* one byte of padding to ensure alignment of whole struct in arrays */ } #define P(X) printf("sizeof struct %s == %ld\n", #X, sizeof (struct X)) int main() { P(A); P(B); P(C); P(D); } /* main */ 

如您所见, struct A类型所需的对齐(1字节)允许将其放在内存中的任何位置,并确定不需要填充字节来确定sizeof值。

在第二个例子中,我们引入了一个int值,它强制整个struct对齐(因此int可以在正确对齐的内存地址中访问)所以这次,编译器已填充(在结构的末尾)额外的字节,因此指定类型的任何数组类型都能正确对齐,并且在有效地址访问其int字段。

在第三个例子中,我说明了第二个例子中填充的效果是由于结构中存在的int字段,因为第三个例子具有相同的大小字段,但这次是一个不需要的对齐字段,所以没有填充已插入,因为内部的所有单个数据类型都需要对齐1。

输出(在我的系统上,MAC OSX系统)是:

 sizeof struct A == 3 sizeof struct B == 8 sizeof struct C == 7 sizeof struct D == 12