Pointers are not arrays. The basic reasons for choosing which to use are the same as they always are with arrays versus pointers. In the special case of flexible array members, here are some reasons you may prefer them over a pointer:

  • Reducing storage requirements. A pointer will enlarge your structure by (typically) 4 or 8 bytes, and you'll spend much more in overhead if you allocate the pointed-to storage separately rather than with a single call to malloc.

  • Improving access efficiency. A flexible array member is located at a constant offset from the structure base. A pointer requires a separate dereference. This affects both number of instructions required to access it, and register pressure.

  • Atomicity of allocation success/failure. If you allocate the structure and allocate storage for it to point to as two separate steps, your code for cleaning up in the failure cases will be much uglier, since you have the case where one succeeded and the other failed. This can be avoided with some pointer arithmetic to carve both out of the same malloc request, but it's easy to get the logic wrong and invoke UB due to alignment issues.

  • Avoiding need for deep-copy. If you use a flexible array instead of a pointer, you can simply memcpy (not assign, since assignment can't know the flexible array length) to copy the structure rather than having to copy the pointed-to data too and fix up the pointer in the new copy.

  • Avoiding need for deep-free. It's very convenient and clean to be able to just free a single object rather than having to free pointed-to data too. This can also be achieved with the "carving up a single malloc" approach mentioned above, of course, but flexible arrays make it easier and less error-prone.

  • Surely many more reasons...

Answer from R.. GitHub STOP HELPING ICE on Stack Overflow
Top answer
1 of 2
34

Pointers are not arrays. The basic reasons for choosing which to use are the same as they always are with arrays versus pointers. In the special case of flexible array members, here are some reasons you may prefer them over a pointer:

  • Reducing storage requirements. A pointer will enlarge your structure by (typically) 4 or 8 bytes, and you'll spend much more in overhead if you allocate the pointed-to storage separately rather than with a single call to malloc.

  • Improving access efficiency. A flexible array member is located at a constant offset from the structure base. A pointer requires a separate dereference. This affects both number of instructions required to access it, and register pressure.

  • Atomicity of allocation success/failure. If you allocate the structure and allocate storage for it to point to as two separate steps, your code for cleaning up in the failure cases will be much uglier, since you have the case where one succeeded and the other failed. This can be avoided with some pointer arithmetic to carve both out of the same malloc request, but it's easy to get the logic wrong and invoke UB due to alignment issues.

  • Avoiding need for deep-copy. If you use a flexible array instead of a pointer, you can simply memcpy (not assign, since assignment can't know the flexible array length) to copy the structure rather than having to copy the pointed-to data too and fix up the pointer in the new copy.

  • Avoiding need for deep-free. It's very convenient and clean to be able to just free a single object rather than having to free pointed-to data too. This can also be achieved with the "carving up a single malloc" approach mentioned above, of course, but flexible arrays make it easier and less error-prone.

  • Surely many more reasons...

2 of 2
1

Those concepts are definitely not necessary as you have pointed out yourself.

The differences between the two that you have demonstrated are where your data is located in memory.

In the first example with flexible array your metadata and the array itself are in the same block of memory and can be moved as one block (pointer) if you have to.

In the second example your metadata is on the stack and your array is elsewhere on the heap. In order to move/copy it you will now need to move two blocks of memory and update the pointer in your metadata structure.

Generally flexible size arrays are used when you need to place an array and it's metadata spatially together in memory.

An example where this is definitely useful is for instance when placing an array with it's metadata in a file - you have only one continuous block of memory and each time you load it it will (most likely) be placed in a different location of your VM.

Top answer
1 of 1
13

Before we get to the pros and cons, let's look at some real-world examples.

Let's say we wish to implement a hash table, where each entry is a dynamically managed array of elements:

struct hash_entry {
    size_t              allocated;
    size_t              used;
    element             array[];
};

struct hash_table {
    size_t              size;
    struct hash_entry **entry;
};
#define HASH_TABLE_INITIALIZER { 0, NULL }

This in fact uses both. The hash table itself is a structure with two members. The size member indicates the size of the hash table, and the entry member is a pointer to an array of hash table entry pointers. This way, each unused entry is just a NULL pointer. When adding elements to a hash table entry, the entire struct entry can be reallocated (for sizeof (struct entry) + allocates * sizeof (element) or freed, as long as the corresponding pointer in the entry member in the struct hash_table is updated accordingly.

If we used element *array instead, we would need use struct hash_entry *entry: in the struct hash_table; or allocate the struct hash_entry separately from the array; or allocate both struct hash_entry and array in the single chunk, with the array pointer pointing just after the same struct hash_entry.

The cost of that would be two extra size_ts worth of memory used for each unused hash table slot, as well as an extra pointer dereference when accessing elements. (Or, to get the address of the array, two consecutive pointer dereferences, instead of one pointer dereference plus offset.) If this is a key structure heavily used in an implementation, that cost can be visible in profiling, and negatively affect cache performance. For random accesses, the larger the element array is, the less difference there is, however; the cost is largest when the arrays are small, and fit within the same cacheline (or a few cachelines) as the allocated and used members.

We do not usually want to make the entry member in the struct hash_table a flexible array member, because that would mean you no longer can declare a hash table statically, using struct hash_table my_table = HASH_TABLE_INITIALIZER;; you would need to use a pointer to a table, and an initializer function: struct hash_table *my_table; my_table = hash_table_init(); or similar.

I do have another example of related data structures using both pointer members and flexible array members. It allows one to use variables of type matrix to represent any 2D matrix with double entries, even when a matrix is a view to another (say, a transpose, a block, a row or column vector, or even a diagonal vector); these views are all equal (unlike in e.g. GNU Scientific Library, where matrix views are represented by a separate data type). This matrix representation approach makes writing robust numerical linear algebra code easy, and the ensuing code is much more readable than when using GSL or BLAS+LAPACK. In my opinion, that is.


So, let's look at the pros and cons, from the point of view of how to choose which approach to use. (For that reason, I will not designate any feature as "pro" or "con", as the determination depends on the context, on each particular use case.)

  • Structures with flexible array members cannot be initialized statically. You can only refer to them via pointers.

    You can declare and initialize structures with pointer members. As shown in above example, using a preprocessor initializer macro can mean you do not need an initializer function. For example, a function accepting a struct hash_table *table parameter can always resize the array of pointers using realloc(table->entry, newsize * sizeof table->entry[0]), even when table->entry is NULL. This reduces the number of functions needed, and simplifies their implementation.
     

  • Accessing an array via a pointer member can require an extra pointer dereference.

    If we compare the accesses to arrays in statically initialized structures with pointer to the array, to a structure with a flexible array member referred via a static pointer, the same number of dereferences are made.

    If we have a function that gets the address of a structure as a parameter, then accessing an array element via a pointer member requires two pointer dereferences, whereas accessing a flexible array element requires only one pointer dereference and one offset. If the array elements are small enough and the array index small enough, so that the accessed array element is in the same cacheline, the flexible array member access is often significantly faster. For larger arrays, the difference in performance tends to be insignificant. This does vary between hardware architectures, however.
     

  • Reallocating an array via a pointer member hides the complexity from those using the structure as an opaque variable.

    This means that if we have a function that receives a pointer to a structure as a parameter, and that structure has a pointer to a dynamically allocated array, the function can reallocate that array without the caller seeing any change in the structure address itself (only structure contents change).

    However, if we have a function that receives a pointer to a structure with a flexible array member, reallocating the array means reallocating the entire structure. That potentially modifies the address of the structure. Because the pointer is passed by value, the modification is not visible to the caller. Thus, a function that may resize a flexible array member, must receive a pointer to a pointer to the structure with a flexible array member.

    If the function only examines the contents of a structure with a flexible array member, say counts the number of elements that fulfill some criteria, then a pointer to the structure suffices; and both the pointer and the pointed-to data can be marked const. This might help the compiler produce better code. Furthermore, all the data accessed is linear in memory, which helps more complex processors manage caching more efficiently. (To do the same with an array having a pointer member, one would need to pass the pointer to the array, as well as the size field at least, as parameters to the counting function, instead of a pointer to the structure containing those values.)
     

  • An unused/empty structure with a flexible array member can be represented by a NULL pointer (to such structure). This can be important when you have an array of arrays.

    With structures with flexible array members, the outer array is just an array of pointers. With structures with pointer members, the outer array can be either an array of structures, or an array of pointers to structures.

    Both can support different types of sub-arrays, if the structures have a common type tag as the first member, and you use an union of those structures. (What 'use' means in this context, is unfortunately debatable. Some claim you need to access the array via the union, I claim the visibility of such an union is sufficient because anything else will break a huge amount of existing POSIX C code; basically all server-side C code using sockets.)

Those are the major ones I can think of right now. Both forms are ubiquitous in my own code, and I have had no issues with either. (In particular, I prefer using a structure free helper function that poisons the structure to help detect use-after-free bugs in early testing; and my programs do not often have any memory-related issues.)

I will edit the above list, if I find I've missed important facets. Therefore, if you have a suggestion or think I've overlooked something above, please let me know in a comment, so I can verify and edit as appropriate.

🌐
Red Hat
developers.redhat.com › articles › 2022 › 09 › 29 › benefits-limitations-flexible-array-members
The benefits and limitations of flexible array members | Red Hat Developer
August 14, 2023 - With the pointer implementation, adding an array element requires an extra load initializing the structure on the heap. Each element added to the array requires two allocations for the object and its data member.
🌐
Oracle
docs.oracle.com › cd › E19205-01 › 819-5265 › bjazj › index.html
D.1.8 Flexible Array Members (Sun Studio 12: C User's Guide)
Because the compiler supports incomplete array types, you can achieve the same result without declaring the array with one member: You now declare a pointer dd and allocate memory as before, except that it is no longer necessary to subtract one from actual_size:

Pointers are not arrays. The basic reasons for choosing which to use are the same as they always are with arrays versus pointers. In the special case of flexible array members, here are some reasons you may prefer them over a pointer:

  • Reducing storage requirements. A pointer will enlarge your structure by (typically) 4 or 8 bytes, and you'll spend much more in overhead if you allocate the pointed-to storage separately rather than with a single call to malloc.

  • Improving access efficiency. A flexible array member is located at a constant offset from the structure base. A pointer requires a separate dereference. This affects both number of instructions required to access it, and register pressure.

  • Atomicity of allocation success/failure. If you allocate the structure and allocate storage for it to point to as two separate steps, your code for cleaning up in the failure cases will be much uglier, since you have the case where one succeeded and the other failed. This can be avoided with some pointer arithmetic to carve both out of the same malloc request, but it's easy to get the logic wrong and invoke UB due to alignment issues.

  • Avoiding need for deep-copy. If you use a flexible array instead of a pointer, you can simply memcpy (not assign, since assignment can't know the flexible array length) to copy the structure rather than having to copy the pointed-to data too and fix up the pointer in the new copy.

  • Avoiding need for deep-free. It's very convenient and clean to be able to just free a single object rather than having to free pointed-to data too. This can also be achieved with the "carving up a single malloc" approach mentioned above, of course, but flexible arrays make it easier and less error-prone.

  • Surely many more reasons...

Answer from R.. GitHub STOP HELPING ICE on Stack Overflow
🌐
Wikipedia
en.wikipedia.org › wiki › Flexible_array_member
Flexible array member - Wikipedia
February 7, 2026 - C struct data types may end with a flexible array member with no specified size: typedef struct { size_t len; // there must be at least one other data member double arr[]; // the flexible array member must be last // The compiler may reserve extra padding space here, like it can between struct ...
Top answer
1 of 2
1

The difference is how the struct is stored. In the first example you over-allocate memory but that doesn't magically mean that the data pointer gets set to point at that memory. Its value after malloc is in fact indeterminate, so you can't reliably print it.

Sure, you can set that pointer to point beyond the part allocated by the struct itself, but that means potentially slower access since you need to go through the pointer each time. Also you allocate the pointer itself as extra space (and potentially extra padding because of it), whereas in a flexible array member sizeof doesn't count the flexible array member. Your first design is overall much more cumbersome than the flexible version, but other than that well-defined.

The reason why people malloc twice when using a struct with pointers could either be that they aren't aware of flexible array members or using C90, or alternatively that the code isn't performance-critical and they just don't care about the overhead caused by fragmented allocation.

2 of 2
0

I am wondering whether it is safe and able to malloc struct with pointers like this, and what is the exactly reason programmers malloc twice when using struct with pointers.

If you use pointer method and malloc only once, there is one extra thing you need to care of in the calculation: alignment.

Let's add one extra field to the structure:

struct Vector {
    size_t size;
    uint32_t extra;        
    double *data;
};

Let's assume that we are on system where each field is 4 bytes, there is no trailing padding on struct and total size is 12 bytes. Let's also assume that double is 8 bytes and requires alignment to 8 bytes.

Now there is a problem: expression (char*)newVector + sizeof*newVector no longer gives address that is divisible by 8. There needs to be manual padding of 4 bytes between structure and data. This complicates the malloc size calculation and data pointer offset calculation.

So the main reason you see 1 malloc pointer version less, is that it is harder to get right. With pointer and 2 mallocs, or flexible array member, compiler takes care of necessary alignment calculation and padding so you don't have to.

Find elsewhere
🌐
SEI CERT
wiki.sei.cmu.edu › confluence › display › c › DCL38-C.+Use+the+correct+syntax+when+declaring+a+flexible+array+member
DCL38-C. Use the correct syntax when declaring a flexible array member - SEI CERT C Coding Standard - Confluence
In particular, the size of the structure is as if the flexible array member were omitted except that it may have more trailing padding than the omission would imply. However, when a . (or ->) operator has a left operand that is (a pointer to) a structure with a flexible array member and the right operand names that member, it behaves as if that member were replaced with the longest array (with the same element type) that would not make the structure larger than the object being accessed; the offset of the array shall remain that of the flexible array member, even if this would differ from that of the replacement array.
🌐
Quora
quora.com › How-do-I-properly-get-a-pointer-for-a-flexible-array-member-thats-inside-a-struct
How to properly get a pointer for a flexible array member that's inside a struct - Quora
Answer: In C you only have one option: use T* in your struct: [code]struct Blah { T* pFlexArray; }; [/code]Best is to set all these pointers to NULL if you have multiple structs, or to assign room for your array. You will have to use malloc or realloc. It is good practise to let your array g...
Top answer
1 of 2
7

Structures with a flexible array as their last member cannot be used as members of other structures or as array elements. In such constructions, the flexible array cannot be used as it has a size of 0 elements. The C Standard quoted by Jonathan Leffler is explicit, although the language used is quite technical and the paragraphs cannot be found in the Standard by searching for flexible.

The compiler should have issued an error for your array of struct vector.

In your program, you should instead use an array of pointers to struct vectors, each pointing to an object allocated for the appropriate number of elements in the its flexible array.

Here is a modified version:

Copy#include <stdio.h>
#include <stdlib.h>

struct vector {
    size_t length;
    double array[];
};

struct vector *make_vector(size_t n) {
    struct vector *v = malloc(sizeof(*v) + n * sizeof(v->array[0]));
    v->length = n;
    for (size_t i = 0; i < n; i++) {
        v->array[i] = (double)i;
    }
    return v;
}

int main(void) {
    struct vector *arr[3];

    arr[0] = make_vector(10);
    arr[1] = make_vector(5);
    arr[2] = make_vector(20);

    for (size_t n = 0; n < 3; n++) {
        for (size_t i = 0; i < arr[n]->length; i++) {
            printf("arr[%zu]->array[%2zu] equals %2.0lf.\n",
                   n, i, arr[0]->array[i]);
        }
    }
    return 0;
}
2 of 2
3

You can't have arrays of structures with flexible array members.

The C standard, ISO/IEC 9899:2011, says:

6.7.2.1 Structure and union specifiers

¶3 A structure or union shall not contain a member with incomplete or function type (hence, a structure shall not contain an instance of itself, but may contain a pointer to an instance of itself), except that the last member of a structure with more than one named member may have incomplete array type; such a structure (and any union containing, possibly recursively, a member that is such a structure) shall not be a member of a structure or an element of an array.

Emphasis added — the italic part of that prohibits arrays of structures with flexible array members. You can have arrays of pointers to such structures, though, but each structure will be separately allocated.

¶18 As a special case, the last element of a structure with more than one named member may have an incomplete array type; this is called a flexible array member. In most situations, the flexible array member is ignored. In particular, the size of the structure is as if the flexible array member were omitted except that it may have more trailing padding than the omission would imply. However, when a . (or ->) operator has a left operand that is (a pointer to) a structure with a flexible array member and the right operand names that member, it behaves as if that member were replaced with the longest array (with the same element type) that would not make the structure larger than the object being accessed; the offset of the array shall remain that of the flexible array member, even if this would differ from that of the replacement array. If this array would have no elements, it behaves as if it had one element but the behavior is undefined if any attempt is made to access that element or to generate a pointer one past it.

This defines a flexible array member.

If you think about it, it makes sense. Pointer arithmetic and arrays rely on all the objects in the array being the same size (hence the equivalence of a[i] == *(a + i), etc), so having an array of objects of varying size would break pointer arithmetic. An array of pointers isn't a problem because the pointers are all the same size, even if the objects pointed at are of different sizes.

If you manage to get a compiler to ignore the violated constraint, then each element of the array will have a zero length flexible array member because the structures will be treated as having the size of the structure without the array member (that's the 'in most situations, the flexible array member is ignored' rule at work). But the compiler should reject an array of a structure type with a flexible array member; such code is violating a constraint (¶3 is in the constraints section; ¶18 is in the semantics section).

🌐
GeeksforGeeks
geeksforgeeks.org › c language › flexible-array-members-structure-c
Flexible Array Members in a structure in C - GeeksforGeeks
August 20, 2024 - Student_id : 523 Stud_Name : ... of Struct pointer: 8 · Adjacent memory locations are used to store structure members in memory. In previous standards of the C programming language, we were able to declare a zero-size array member in place of a flexible array ...
🌐
Quentin Santos
qsantos.fr › home › flexible array members: typical c shenanigans
Flexible Array Members: Typical C Shenanigans - Quentin Santos
October 1, 2023 - In the second case, we need to first recover the value of the field data, at an offset of 8 bytes from the beginning of the struct, then read at the right offset from the address it contains. In other words, using a pointer instead of a built-in array is twice as slow!
Top answer
1 of 1
25

A flexible array member is an array without a specified size. The member has to be the last member of the struct. The actual array size is set when you allocate memory for the struct. Consequently, it only makes sense together with dynamic allocation.

Example:

#define ARRSIZE 10

struct FAM
{
    size_t sz;
    int arr[];   // Must be last struct member
};

struct FAM* fam = malloc(sizeof(struct FAM) + ARRSIZE * sizeof(int));

Now fam->arr is an array with ARRSIZE elements that you can access ussing fam->arr[index].

Further code like:

struct FAM* famA = malloc(sizeof(struct FAM) + 10 * sizeof(int));
struct FAM* famB = malloc(sizeof(struct FAM) + 1000 * sizeof(int));

will give you two pointers of the same type even though the size of the arrays differ.

So why would I use it?

Look at this code

struct FAM
{
    size_t sz;
    int arr[];
};

struct P
{
    size_t sz;
    int* p;
};

int getFAM(struct FAM* f, unsigned long x)
{
    return f->arr[x];
}

int getP(struct P* p, unsigned long x)
{
    return p->p[x];
}

It's two ways of doing "the same". One using a flexible array member, the other using a pointer.

Compiled with gcc -O2 on https://godbolt.org/ I get

which indicates that the flexible array can save you one indirection and thereby generate faster code.

It can be described like: In case of a flexible array member the array has fixed offset from a struct pointer while in case of a pointer-to-int member the array is located where the pointer value says. Consequently, in the first case the compiler can use that "known fixed offset" directly but in the second case the compiler must read the pointer value first and then read the array data.

Note: This example is for one specific system (aka compiler/cpu type). On other systems the result may differ.

🌐
kees
people.kernel.org › kees › bounded-flexible-arrays-in-c
Bounded Flexible Arrays in C — kees
January 23, 2023 - Any flexible array structures not already using DECLARE_BOUNDED_ARRAY() can be annotated manually with the new attribute. For example, assuming the proposed __attribute__((__counted_by__(member))) is wrapped in a macro named __counted_by(): ... It will also be possible to use the new attribute on pointers and function arguments as well as flexible arrays.
🌐
Stack Overflow
stackoverflow.com › questions › 78882152 › clarification-regarding-flexible-array-member-access
c - Clarification regarding flexible array member access - Stack Overflow
[...] when a . (or ->) operator has a left operand that is a (pointer to) a structure with a flexible array member and the right operand names that member, it behaves as if that member were replaced with the longest array (with the same element type) that would not make the structure larger than the object being accessed; the offset of the array shall remain that of the flexible array member, even if this would differ from that of the replacement array.
🌐
Quora
quora.com › Which-are-some-good-uses-of-flexible-array-member-of-a-struct-introduced-by-C99-standard
Which are some good uses of flexible array member of a struct introduced by C99 standard? - Quora
Answer (1 of 2): I use it all the time when dealing with network packets. A packet is a set of headers of various protocols. You might have something like this: ethernet header: 14 bytes IP header: 20 bytes TCP header: 20 bytes data I can define a structure using this: [code c] struct { struc...
Top answer
1 of 4
17

The C FAQ answers precisely this question. The quick answer is that this structure will include the double array inside the structure rather than a pointer to an array outside the structure. As a quick example, you could use your structure as in this example:

struct s *mystruct = malloc(sizeof(struct s) + 5 * sizeof(double));
s->n = 12;
s->d[0] = 4.0;
s->d[1] = 5.0;
s->d[2] = 6.0;

And so on - the size of the array you care about is included in the allocation, and then you can use it just like any array. Normally such a type contains the size as part of the structure, since using the + trick to skip through an array of type s will be necessarily complicated by this situation.

To your added question 'how is this construct any more or less powerful than keeping a [pointer] as the 2nd element?', it's no more powerful per se, but you don't need to keep a pointer around, so you would save at least that much space - also when you are copying the structure, you would also copy the array, rather than a pointer to an array - a subtle difference sometimes, but very important other times. 'You-can-do-it-in-multiple-ways' is probably a good explanation, but there are cases where you would specifically want one design or the other.

2 of 4
7

The primary advantage is that a flexible array member allows you to allocate a single block of memory for the array along with the other data in the struct (with a pointer, you'd typically end up with two separately allocated blocks).

It's also useful with data transmitted by quite a few network protocols, where the incoming stream is defined the same way -- an integer defining a length, followed by that many units (typically bytes/octets) of data. You can (typically) use a type-pun to overlay a struct with a flexible array member onto a buffer filled with such data, and work with it directly instead of having to parse it out into pieces and then work with the pieces individually.

🌐
SonarSource
rules.sonarsource.com › c › rspec-2324
Flexible array members should not be declared
Unique rules to find Bugs, Vulnerabilities, Security Hotspots, and Code Smells in your C code
🌐
Aticleworld
aticleworld.com › home › what is flexible array member in c?
What is flexible array member in C? - Aticleworld
August 30, 2021 - flexible array member enables user to create an empty array in structure, size of array can be changed at run time as per user requirements.