Is it guaranteed to keep array elements in C sequentially, without padding?

In other words: is it guaranteed that if I have an array allocated like this:

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

      

Then elta

, eltb

, eltc

will point to the same location in memory, which is the second element of the type some_type

of the array?

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

      

The reason I am asking this is because I am trying to make a "container" in C and if that fails then Im out of ideas will return a pointer to any other element than the first one.

+3


source to share


2 answers


Yes, it's guaranteed. If padding bytes are added, they are added within struct some_type

, but not between, two array elements.

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;

      

With a byte alignment adjusted to 4 or 8 (or even greater powers of 2), this structure will be 8, and d will be 8, with bytes set to 1 or 2, the structure will be 6 as d ...



Note. This is not the only place where there may be bytes filling: If you switch elements n

and s

to fill n

it would be necessary to align the bytes between s

and n

, on the other hand, no bytes will not be necessary after filling n, as size of the structure will ensure proper alignment already.

Referring to the standard: C11, 6.2.5.20:

An array type describes a contiguous allocated non-empty set of objects with a specific member object type called the element type. 36) Types of arrays are characterized by their element type and the number of elements in the array. [...]

(Emphasizing me!).

+7


source


Data reconciliation is tricky, as shown in the following example (which you can even do to do your own experiments):

#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 */

      

As you can see, the required alignment (1 byte) of the type struct A

allows it to be placed anywhere in memory and determines that sizeof

no padding bytes are required to determine the value .

In the second example, we introduced a value int

that forces the integer to struct

be word-aligned (so that int is accessible at a properly aligned memory address), so this time the compiler has filled (at the end of the structure) for additional bytes, so any array type of the specified type gets the correct alignment and the field is int

accessed by a valid address.



In the third example, I illustrate that the padding effect in the second example is related to the margin int

present in the outline, since the third example has the same size box, but this time no alignment of the margin is required, so no padding was inserted since everything individual datatypes inside need alignment 1.

Output (on my system, MAC OSX system):

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

      

0


source







All Articles