What is flexible array member in C?

flexible array member in c

flexible array member introduced in C99. This feature enables the user to create an empty array in a structure. The size of the empty array can be changed at runtime as per the user requirements. But this empty array must be declared as the last member of the structure and the structure must contain at least one or more named members.

 

According to C99, “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”.

 

Note: When a structure has a flexible array member, the entire structure becomes an incomplete type. Basically, an incomplete type structure is a type that has a lack of information about its members.

 

Let’s see some examples of the incomplete types that might be helpful for you.

1.  An array type whose dimension is not specified.
2. A structure type whose members not specified completely.
3. A union type whose members not specified completely.

 

Example of flexible array member in C:

Below structure struct s has a flexible array member d. You can see that the last element is an incomplete array and the struct also have some named members. It is a basic condition of the flexible array member.

//Example of a flexible array member

struct s
{
    int n;
    double d[];
};

 

A typical way to use this is:

 

int m = /* some value */;

struct s *p = malloc(sizeof (struct s) + sizeof (double [m]));


If the call to malloc succeeds, the object pointed to by p behaves, for most purposes, as if p had been declared as:

struct
{
    int n;
    double d[m];
} *p;

Note: there are circumstances in which this equivalence is broken; in particular, the offsets of member d might not be the same.

 

 

What must be the size of the structure that have flexible array member?

Let’s consider the below structure that has a flexible array member.  I am going to explain that what will be the size of the structure which has an incomplete array type.

//incomplete structure
typedef struct
{
    int iEmpId;
  
    float fSalary;
  
    char acName[];//incomplete array

} sEmployInfo;

 

When we calculating the size of the above structure then we found that the size of the structure includes all the member’s sizes including the padding bytes (if required) but not including the size of the flexible array member.

For example, if the size of an int and float is 4 bytes and the alignment of the sEmployInfo is also 4 bytes, then the compiler will likely insert no padding bytes after the members. And the size of the structure will be 8 bytes.

If we are talking about the C99 standard statement, then they said that “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.”

 

C program to calculate the size of the structure:

Let’s see a C program in which we are calculating the size of the structure that has an incomplete type array. We are taking the above-mentioned structure.

#include <stdio.h>


typedef struct
{
    int iTrackNumber;
    float fAmount;
    char acAddress[];// flexible array member
} sInformation;


int main()
{
    printf("Size of structure = %d\n",sizeof(sInformation));

    return 0;
}

Output:

flexible array member c99

 

Why does a flexible array require?

To understand the above question we need to take an example. Suppose there is an application that has a structure that contains the character array whose size is 30 bytes. This array is used to store the address of the user. Here, problem is that when you create a variable using this structure then every time the compiler will reserve 30 bytes for the array.

If the length of the user address is less than 30 bytes, the extra remaining memory of the array would be a wastage. In some scenarios, it can be possible the length of the address could be greater than 30 bytes, this type of situation creates a problem, and might be you will get boundary issues.

Let’s see a C program to understand the above describe issue. We are dividing the C code into two parts where the address is less than 30 bytes and greater than 30 bytes.

1. Address less than 30 bytes:

 

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


// A structure to store employee information
typedef struct EmpInformation
{
    int Emp_id;
    int Salary;
    char Address[30];
} sEmpInformation;
typedef sEmpInformation* psEmpInformation;



// Allocate the memory and initialize struct EmpInformation
psEmpInformation ComposeEmpInfo( int salary,int id, const char *pcAddress)
{
    // Allocating memory for sEmpInformation
    psEmpInformation psEmpInfo = malloc(sizeof(*psEmpInfo));
    if(psEmpInfo != NULL)
    {
        psEmpInfo->Emp_id = id;
        psEmpInfo->Salary = salary;
        strcpy(psEmpInfo->Address, pcAddress);
    }
    return psEmpInfo;
}


// Print Employee details
void printEmpInfo(psEmpInformation psEmpInfo)
{
    printf("Emp_id : %d \n\
            Salary : %d  \n\
            Address: %s\n",
           psEmpInfo->Emp_id,psEmpInfo->Salary,psEmpInfo->Address);
}


int main()
{
    psEmpInformation Aticleworld = ComposeEmpInfo(210013,1, "Delhi, India");
    if(Aticleworld != NULL)
    {
        printEmpInfo(Aticleworld);
        free(Aticleworld);
    }
    return 0;
}

Output:

use of flexible array

 

2. Address greater than 30 bytes:

 

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


// A structure to store employe information
typedef struct EmpInformation
{
    int Emp_id;
    int Salary;
    char Address[30];
} sEmpInformation;
typedef sEmpInformation* psEmpInformation;


// Allocate the memory and initialize the structure
psEmpInformation ComposeEmpInfo( int salary,int id, const char *pcAddress)
{
    // Allocating memory for struct EmpInformation
    psEmpInformation psEmpInfo = malloc(sizeof(*psEmpInfo));
    if(psEmpInfo != NULL)
    {
        psEmpInfo->Emp_id = id;
        psEmpInfo->Salary = salary;
        strcpy(psEmpInfo->Address, pcAddress);
    }
    return psEmpInfo;
}

// Print student details
void printEmpInfo(psEmpInformation psEmpInfo)
{
    printf("Emp_id : %d \
            Salary : %d  \
            Address: %s\n",
           psEmpInfo->Emp_id,psEmpInfo->Salary,psEmpInfo->Address);
}


int main()
{
    psEmpInformation Aticleworld = ComposeEmpInfo(1,100013, "Preet vihar\
                                                   street-abcd ,block\
                                                   abcxyz, New Delhi, India");
    if(Aticleworld != NULL)
    {
        printEmpInfo(Aticleworld);
        free(Aticleworld);
    }
    return 0;
}

Output:

flexible array c99

 

So to resolve the above problem we need a dynamic array, previously many people use struct hack but later C99 introduces the concept of flexible array member in C language. Flexible array members enable you to create a dynamic size array as per the requirements at run-time.

 

If you want to learn more about the c language, here 10 Free days C video course for you.

Your free trial is waiting

 

How to use flexible array member in C

In the below program, I have created a flexible array in the structure in place of the static size array whose size is fixed( 30 bytes). We can change the size of the flexible array at runtime. In the example code, I have created two variables that can store the address less than 30 and greater than 30 bytes.

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

// A structure to store employee information
typedef struct EmpInformation
{
    int Emp_id;
    int Salary;
    char Address[];
} sEmpInformation;
typedef sEmpInformation* psEmpInformation;

//Note use string function carefully

// Allocate the memory and initialize the structure
psEmpInformation ComposeEmpInfo( int salary,int id, const char *pcAddress)
{
    // Allocating memory as per the requirements
    psEmpInformation psEmpInfo = malloc( sizeof(*psEmpInfo) + sizeof(char) * strlen(pcAddress) + 1);
    if(psEmpInfo != NULL)
    {
        psEmpInfo->Emp_id = id;
        psEmpInfo->Salary = salary;
        strcpy(psEmpInfo->Address, pcAddress);
    }
    return psEmpInfo;
}
// Print student details
void printEmpInfo(psEmpInformation psEmpInfo)
{
    printf("Emp_id : %d \
            Salary : %d  \
            Address: %s\n",
           psEmpInfo->Emp_id,psEmpInfo->Salary,psEmpInfo->Address);
}


int main()
{
    psEmpInformation Amlendra = ComposeEmpInfo(1,100013, "Preet vihar \ street-abcd ,\
                                               \block abcxyz, \
                                               New Delhi,\
                                                India");
    if(Amlendra != NULL)
    {
        printEmpInfo(Amlendra);
        free(Amlendra);
    }
    Amlendra = NULL;

    psEmpInformation Aticleworld = ComposeEmpInfo(13,200013, "New Delhi, India");
    if(Aticleworld != NULL)
    {
        printEmpInfo(Aticleworld);
        free(Aticleworld);
    }

    return 0;
}

Output:

 

Recommended Posts for you

15 comments

  1. If you are allowed to use malloc(), then no need of all this circus.
    Just define a pointer of the type you need and do malloc() or realloc().
    That would do the same thing.
    How is your approach better than this?

    1. When you create a pointer in structure then it requires extra bytes of memory which increase the size of the structure and you have to explicitly allocate the memory for the pointer and separately need to free the allocated memory.

  2. The last line of printEmpInfo() function has a spurious extra argument to printf(): sizeof(psEmpInfo)

  3. is it really mandatory to use struct hack using empty sized char array(char emp[0]) or can it be empty size integer array or any type array. for example:
    struct data
    {
    int key;
    char name[10];
    float f;
    int arr[0] ; <— will this work.
    }

Leave a Reply

Your email address will not be published. Required fields are marked *