Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/64.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
是否保证C中的数组元素将连续存储,而不进行填充?_C_Arrays_Padding_Memory Alignment_Pointer Arithmetic - Fatal编程技术网

是否保证C中的数组元素将连续存储,而不进行填充?

是否保证C中的数组元素将连续存储,而不进行填充?,c,arrays,padding,memory-alignment,pointer-arithmetic,C,Arrays,Padding,Memory Alignment,Pointer Arithmetic,换句话说:如果我以这种方式分配了一个数组,是否可以保证: void *arr = calloc(nmemb, sizeof(some_type)) 然后elta,eltb,eltc都将指向内存中的同一位置,这将是该数组的第二个类型的元素 some_type *elta = &((some_type*)arr)[1]; some_type *eltb = ((some_type*)arr)+1; some_type *eltc = (char*)arr+sizeof(some_type)

换句话说:如果我以这种方式分配了一个数组,是否可以保证:

void *arr = calloc(nmemb, sizeof(some_type))
然后
elta
eltb
eltc
都将指向内存中的同一位置,这将是该数组的第二个
类型的元素

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
中,但不会添加到两个数组元素之间

例如:

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,就像d一样

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

参考标准:C11,6.2.5.20:

数组类型描述了一组连续分配的非空对象,这些对象具有特定的成员对象类型,称为元素类型。36)数组类型以其元素类型和数组中元素的数量为特征。[……]


(由我突出显示!)

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


为什么会有一些填充物?当您
malloc(nmemb*sizeof(some_type))
时,您没有填充。数组在哪里?
((some_type*)arr)++
您不能发布增量右值。再次询问,数组在哪里?@gaazkam指针不是数组,请注意:)这是什么语法:
无符号字符:8?我以前从未见过这样的语法。什么是
字节对齐
?字节与字节以外的任何内容对齐,即
1
。在
短字符
和无符号字符`之间不一定有填充-通常没有。@gaazkam这是一个。我用它来添加匿名字节…@Olaf好吧,请看我的评论:“这只是为了说明字节填充的位置”——宏不存在,当然,它应该表示编译器设置,无符号字符位字段被认为表示填充字节。这不是很明显吗?@Aconcagua:填充字节可以出现在结构中的任何字段之后。无法保证特定的布局。这取决于目标平台的实现和ABI。还要注意,C99不是C标准。它在6年前随着C11的发布而被取消。
#include <stdio.h>
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 */
sizeof struct A == 3
sizeof struct B == 8
sizeof struct C == 7
sizeof struct D == 12