🌐
GNU
gcc.gnu.org › onlinedocs › gcc › Zero-Length.html
Zero Length (Using the GNU Compiler Collection (GCC))
The GCC extension accepts a structure containing an ISO C99 flexible array member, or a union containing such a structure (possibly recursively) to be a member of a structure.
C language feature in which a struct may contain as its last member an array with no specified size
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[]; … Wikipedia
🌐
Wikipedia
en.wikipedia.org › wiki › Flexible_array_member
Flexible array member - Wikipedia
February 7, 2026 - 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 members } DoubleArray;
Discussions

Are the flexible array member extensions of GCC mostly useless?
I can't imagine a use foe the empty struct. So that's probably useless. How does embedding these structs not at the end of a struct even work? The one extension that seems neat is static initialization of flexible array members. No idea how useful that is though. More on reddit.com
🌐 r/C_Programming
23
26
December 14, 2021
c++ - Flexible array error with gcc 6 but not with gcc 4 - Stack Overflow
Does anybody know why this happens ... to make gcc 6 compile without errors (I have no chance of changing the code, it's not under my control)? ... Please include the code in the question, or at least a code sample that reproduces the problem. ... In C, a flexible array member (added in ... More on stackoverflow.com
🌐 stackoverflow.com
c - How to initialize a structure with flexible array member - Stack Overflow
The only way to create an instance of a structure with a flexible array member which actually has elements in this array is to dynamically allocate memory for it, for example with malloc. ... There's a GCC extension that lets you specify the flexible array member using that same syntax, if ... More on stackoverflow.com
🌐 stackoverflow.com
Flexible Array Members for C++
ಠ_ಠ Feature: FAMs can only be created with new This sounds highly unintuitive, as typically one would not expect new'd members to be allocated in-place. More on reddit.com
🌐 r/cpp
37
26
October 19, 2018
🌐
GNU
gcc.gnu.org › onlinedocs › gcc › Flexible-Array-Members-alone-in-Structures.html
Flexible Array Members alone in Structures (Using the GNU Compiler Collection (GCC))
Next: Unnamed Structure and Union Fields, Previous: Unions with Flexible Array Members, Up: Array, Union, and Struct Extensions [Contents][Index] GCC permits a C99 flexible array member (FAM) to be alone in a structure:
🌐
GNU
gcc.gnu.org › onlinedocs › gcc › Flexible-Array-Members-in-Unions.html
Flexible Array Members in Unions (Using the GNU Compiler Collection (GCC))
Next: Structures with only Flexible Array Members, Previous: Structures with No Members, Up: Array, Union, and Struct Extensions [Contents][Index] GCC permits a C99 flexible array member (FAM) to be in a union:
🌐
Reddit
reddit.com › r/c_programming › are the flexible array member extensions of gcc mostly useless?
r/C_Programming on Reddit: Are the flexible array member extensions of GCC mostly useless?
December 14, 2021 -

Are people really using gcc extensions for flexible array members?

When I look at them, it's more like they're there to make the behavior to conform to the old int y[0] style of pre-C99 syntax.

Some examples:

struct Foo {
  int x;
  int y[];
}; 

// Extension: embedding the struct as but not as
// the last member
struct Bar {
  struct Foo x;
  int t; 
};

// Extension: putting it in an array
struct Bar g[12];

// Extension: empty array in struct
// so not strictly a flexible array member
struct Baz {
  int y[0]
}

Do people use these in the wild or are they mostly useless? (Obviously the situation is somewhat different for C++, since things like empty structs can be used to guide templates and dispatch)

🌐
Oracle
blogs.oracle.com › linux › improving-gcc-buffer-overflow-detection-for-c-flexible-array-members
https://blogs.oracle.com/linux/improving-gcc-buffer-overflow-detection-for-c-flexible-array-members
November 21, 2025 - In GCC15, we introduced a new GNU C variable attribute, counted_by, to enable programmers to annotate the FAM field with its associated size information. counted_by (count) is defined in the GCC manual as: “The counted_by attribute may be attached to the C99 flexible array member of a structure.
🌐
GeeksforGeeks
geeksforgeeks.org › c language › flexible-array-members-structure-c
Flexible Array Members in a structure in C - GeeksforGeeks
August 20, 2024 - For the structures in C programming language from C99 standard onwards, we can declare an array without a dimension and whose size is flexible in nature. Such an array inside the structure should preferably be declared as the last member of ...
Find elsewhere
🌐
GNU
gnu.org › software › c-intro-and-ref › manual › html_node › Flexible-Array-Fields.html
Flexible Array Fields (GNU C Language Manual)
The C99 standard adopted a more complex equivalent of zero-length array fields. It’s called a flexible array, and it’s indicated by omitting the length, like this:
🌐
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
Flexible array members are a special type of array in which the last element of a structure with more than one named member has an incomplete array type; that is, the size of the array is not specified explicitly within the structure. This "struct hack" was widely used in practice and supported ...
🌐
kees
people.kernel.org › kees › bounded-flexible-arrays-in-c
Bounded Flexible Arrays in C — kees
January 23, 2023 - For well-described flexible array structs, this means associating the member holding the element count with the flexible array member. This idea is not new, though prior implementation proposals have wanted to make changes to the C language syntax. A simpler approach is the addition of struct member attributes, and is under discussion and early development by both the GCC and Clang developer communities.
🌐
Narkive
gcc-help.gcc.gnu.narkive.com › wHJajcCF › flexible-array-member-initializers
Flexible array member initializers
I define the acceptable options in terms of flexible types: struct foo_type { const char *name; int (*parse_fn)(void *dest, const char *text); int (*format_fn)(char *buf, size_t buf_size, const void *value); void (*free_fn)(void *default_value); size_t size; }; struct foo_opt { const char *name; const struct foo_type *type; unsigned char flags; unsigned char def_val[]; }; Note the use of the flexible array member to hold the default value (or possible a pointer to the default value, depending on the type.)
🌐
GNU
gcc.gnu.org › legacy-ml › gcc-patches › 2017-12 › msg00507.html
Jakub Jelinek - [C++ PATCH] Harmonize C++ flexible array member initialization with C (P
ax; }; + +void fBx1 () +{ + BAx bax1 = { 1, /* Ax = */ { 2, /* a[] = */ { 3 } } }; // { dg-error "initialization of flexible array member in a nested context" } + + new (bax1.ax.a) char; // { dg-warning "placement" } + new (bax1.ax.a) char[2]; // { dg-warning "placement" } + new (bax1.ax.a) Int16; // { dg-warning "placement" } + new (bax1.ax.a) Int32; // { dg-warning "placement" } +} + +void fBx2 () +{ + BAx bax2 = { 1, /* Ax = */ { 2, /* a[] = */ { 3, 4 } } }; // { dg-error "initialization of flexible array member in a nested context" } + + new (bax2.ax.a) char; // { dg-warning "placement" }
🌐
Google Open Source
opensource.googleblog.com › 2024 › 07 › bounds-checking-flexible-array-members.html
Bounds Checking Flexible Array Members | Google Open Source Blog
July 9, 2024 - The alloc_size attribute on malloc() may be used for bounds checking flexible array members within the same function as the allocation. But the attribute's information isn't carried with the allocated object, making it impossible to perform bounds checking elsewhere. To mitigate this drawback, Clang and GCC are introducing1 the counted_by attribute for flexible array members.
🌐
GNU
gcc.gnu.org › onlinedocs › gcc-3.1.1 › gcc › Zero-Length.html
Using the GNU Compiler Collection (GCC)
Instead GCC allows static initialization of flexible array members. This is equivalent to defining a new structure containing the original structure followed by an array of sufficient size to contain the data.
Top answer
1 of 1
1

In C (C99 and later), a flexible array member can be defined with [], and must be the last member of a structure. C++ doesn't support flexible array members, but g++ permits them as a language extension.

Older versions of g++ do not require a flexible array member to be the last member of a class or struct. This is a bug, which has been corrected in newer versions of g++.

Here's a small test program, based on yours that illustrates the problem:

#include <iostream>
#include <cstddef>

static int mem[100];

struct test{
        int a;
        int b[];
        int c;
};

int main(){     
    test *ptr = (test*)&mem;
    ptr->a = 10;
    ptr->b[0] = 20;
    ptr->b[1] = 30;
    ptr->c = 40;

    std::cout << "ptr->a    = " << ptr->a << "\n";
    std::cout << "ptr->b[0] = " << ptr->b[0] << "\n";
    std::cout << "ptr->b[1] = " << ptr->b[1] << "\n";
    std::cout << "ptr->c    = " << ptr->c << "\n";
}

And here's the output when I compile it with g++ 4.1.2:

ptr->a    = 10
ptr->b[0] = 40
ptr->b[1] = 30
ptr->c    = 40

As you can see, the member c is allocated at the same offset as b[0].

(Strictly speaking, using an int[] array to hold a test object isn't 100% safe due to possible alignment problems, but that's unlikely to be an issue in practice.)

It's very likely that your code has undiscovered bugs because of this.

Your problem is not that the newer g++ rejects your code; it's that the older one doesn't.

Reordering the member declarations so the flexible array member appears last is the simplest fix -- though you (or someone else) will need to carefully examine how the type is used. A far better solution is probably to replace the flexible array member with some C++ container class, perhaps a std::vector.

(I have no chance of changing the code, it's not under my control)

Somebody is able to change the code, and presumably you're able to submit a bug report.

🌐
GNU
gcc.gnu.org › pipermail › gcc-patches › 2022-August › 599151.html
[GCC13][Patch][V2][1/2]Add a new option -fstrict-flex-array[=n] and attribute strict_flex_array(n) and use it in PR101836
August 1, 2022 - LEVEL=3 is the >>>> strictest level, only when the trailing array is declared as a >>>> flexible array member per C99 standard onwards ([]), it is treated >>>> as a flexible array member. >>>> >>>> There are two more levels in between 0 and 3, which are provided to >>>> support older codes that use GCC zero-length array extension ([0]) >>>> or one-size array as flexible array member ([1]): When LEVEL is 1, >>>> the trailing array is treated as a flexible array member when it is >>>> declared as either [], [0], or [1]; When LEVEL is 2, the trailing >>>> array is treated as a flexible array member when it is declared as >>>> either [], or [0]. >>>> >>>> This attribute can be used with or without '-fstrict-flex-array'.
Top answer
1 of 3
19

No, flexible arrays must always be allocated manually. But you may use calloc to initialize the flexible part and a compound literal to initialize the fixed part. I'd wrap that in an allocation inline function like this:

Copytypedef struct person {
  unsigned age;
  char sex;
  size_t size;
  char name[];
} person;

inline
person* alloc_person(int a, char s, size_t n) {
  person * ret = calloc(sizeof(person) + n, 1);
  if (ret) memcpy(ret,
                  &(person const){ .age = a, .sex = s, .size = n},
                  sizeof(person));
  return ret;
}

Observe that this leaves the check if the allocation succeeded to the caller.

If you don't need a size field as I included it here, a macro would even suffice. Only that it would be not possible to check the return of calloc before doing the memcpy. Under all systems that I programmed so far this will abort relatively nicely. Generally I think that return of malloc is of minor importance, but opinions vary largely on that subject.

This could perhaps (in that special case) give more opportunities to the optimizer to integrate the code in the surroundings:

Copy#define ALLOC_PERSON(A,  S,  N)                                 \
((person*)memcpy(calloc(sizeof(person) + (N), 1),               \
                 &(person const){ .age = (A), .sex = (S) },     \
                 sizeof(person)))

Edit: The case that this could be better than the function is when A and S are compile time constants. In that case the compound literal, since it is const qualified, could be allocated statically and its initialization could be done at compile time. In addition, if several allocations with the same values would appear in the code the compiler would be allowed to realize only one single copy of that compound literal.

2 of 3
8

There are some tricks you can use. It depends on your particular application.

If you want to initialise a single variable, you can define a structure of the correct size:

Copy   struct  {
        int age;
        char sex;
        char name[sizeof("THE_NAME")];
    } your_variable = { 55, 'M', "THE_NAME" };

The problem is that you have to use pointer casting to interpret the variable as "person"(e.g. "*(person *)(&your_variable)". But you can use a containing union to avoid this:

Copyunion {
 struct { ..., char name[sizeof("THE_NAME")]; } x;
 person p;
} your_var = { 55, 'M', "THE_NAME" };

so, your_var.p is of type "person". You may also use a macro to define your initializer, so you can write the string only once:

Copy#define INIVAR(x_, age_, sex_ ,s_) \
   union {\
     struct { ..., char name[sizeof(s_)]; } x;\
     person p;\
    } x_ = { (age_), (sex_), (s_) }

INIVAR(your_var, 55, 'M', "THE NAME");

Another problem is that this trick is not suitable to create an array of "person". The problem with arrays is that all elements must have the same size. In this case it's safer to use a const char * instead of a char[]. Or use the dynamic allocation ;)

🌐
GNU
gcc.gnu.org › onlinedocs › gcc-9.1.0 › gcc › Zero-Length.html
Using the GNU Compiler Collection (GCC): Zero Length
GCC allows static initialization of flexible array members. This is equivalent to defining a new structure containing the original structure followed by an array of sufficient size to contain the data.
🌐
GNU
gcc.gnu.org › legacy-ml › gcc-patches › 2016-09 › msg01469.html
Jason Merrill - Re: [PATCH] accept flexible arrays in struct in unions (c++/71912 - [6/7
I don't >> see why that would affect whether we want to look through intermediate >> non-anonymous classes. > > In code like this: > > struct X { int n, a[]; }; > struct Y { int n, b[]; }; > > struct D: X, Y { }; > > The test above make the diagnostic point to the context of the invalid > flexible array member, or Y::b, rather than that of X.