Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

The approach to acquiring memory in this case is similar to the C99 approach with the exception that 1 is subtracted from array_size to account for the element present in the structure definition. The problem with using this approach is that the behavior is undefined when accessing other than the first element of data (see Section 6.5.6, Paragraph 8 of the C99 standard).   Consequently, the compiler can generate code that does not return the expected value when accessing the second element of data.  Structures with flexible array members can be used to produce code with defined behavior.   However, some restrictions apply:

  1. The incomplete array type must be the last element within the structure.
  2. There cannot be an array of structures that contain flexible array members.
  3. Structures that contain a flexible array member cannot be used as a member in the middle of another structure.

Noncompliant Code Example (Use Flexible Array Members)

When using C99 compliant compilers the The one element array hack described above should must not be used with C99 compliant compilers.

Noncompliant Code Example

In this noncompliant code, just such an a one element array is used where instead of a flexible array member should be used instead.

Code Block
bgColor#FFcccc
struct flexArrayStruct {
  int num;
  int data[1];
};

/* ... */

struct flexArrayStruct *flexStruct;
size_t array_size;
size_t i;

/* Initialize array_size */

/* Dynamically allocate memory for the structure */
flexStruct = (struct flexArrayStruct *)
   malloc(sizeof(struct flexArrayStruct) + sizeof(int) * (array_size - 1));
if (flexStruct == NULL) {
  /* Handle malloc failure */
}

/* Initialize structure */
flexStruct->num = 0;

for (i = 0; i < array_size; i++) {
  flexStruct->data[i] = 0;
}

Wiki Markup
AsThe describedonly above,member thethat problemis withguaranteed thisto codebe isvalid thatin strictly speaking the only member that is guaranteed to be valid is this code is {{flexStruct->data\[0\]}}. Unfortunately, when using compilers that do not support the C99 standard in full, or at all, this approach may be the only solution.  Microsoft Visual Studio 2005, for example, does not implement the C99 syntax.

Compliant Solution

...

This compliant solution uses the C99 flexible array member syntaxFortunately, when working with C99 compliant compilers, the solution is simple - remove the 1 from the array declaration and adjust the size passed to the malloc() call accordingly.  In other words, use flexible array members.

Code Block
bgColor#ccccff
struct flexArrayStruct {
  int num;
  int data[];
};

/* ... */

struct flexArrayStruct *flexStruct;
size_t array_size;
size_t i;

/* Initialize array_size */

/* Dynamically allocate memory for the structure */
flexStruct = (struct flexArrayStruct *)
   malloc(sizeof(struct flexArrayStruct) + sizeof(int) * array_size);
if (flexStruct == NULL) {
  /* Handle malloc failure */
}

/* Initialize structure */
flexStruct->num = 0;

for (i = 0; i < array_size; i++) {
  flexStruct->data[i] = 0;
}

Wiki Markup
In this casecompliant solution, the structure will beis treated as if the member {{data\[\]}} had been declared to be {{data\[array_size\].}}

...