Versions Compared

Key

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

Section 6.5.2.5 of the the C standard [ISO/IEC 9899:1999 (C99) standard 2011] defines a compound literal as [ISO/IEC 9899:1999]

a postfix A postfix expression that consists of a parenthesized type name followed by a brace-enclosed list of initializers. . . . The value of a of the compound literal is that of an unnamed object initiated by the initializer list.

The storage for this object is either static (if the compound literal occurs at file scope) or automatic (if the compound literal occurs at block scope), and the storage duration is associated with its immediate enclosing block ( [ISO/IEC 9899:1999], Section 6.5.2.5.6)2011].

For example, in the function

Code Block

void func(void) {
  int *ip = (int[4]){1,2,3,4};
  /* ... */
}

...

Note that only one object is created per compound literal -- even literal—even if the compound literal appears in a loop and has dynamic initializers ( [ISO/IEC 9899:19992011], Section 6.5.2.5.16).

This recommendation is a specific instance of rule DCL30-C. Declare objects with appropriate storage durations.

...

In this noncompliant code example, the programmer mistakenly assumes that the elements of the ints array of the pointer to int_struct are assigned the addresses of distinct int_struct objects, one for each integer in the range [0, MAX_INTS-1]:

Code Block
bgColor#FFCCCC
langc

#include <stdio.h>

typedef struct int_struct {
  int x;
} int_struct;

#define MAX_INTS 10

int main(void){
  size_t i;
  int_struct *ints[MAX_INTS];

  for (i = 0; i < MAX_INTS; i++) {
    ints[i] = &(int_struct){i};
  }

  for (i = 0; i < MAX_INTS; i++) {
    printf("%d\n", ints[i]->x);
  }
}

...

Because the storage duration of the compound literal is associated with the for loop that contains it, dereferencing ints in the second loop results in undefined behavior 8: an object is referred to outside of its lifetime9 (Annex J of the C standard  [ISO/IEC 9899:2011]).

Even if the region of memory that contained the compound literal is not written to between loops, the print loop will display the value MAX_INTS-1 for MAX_INTS lines. This is contrary to the intuitive expected result, which is that the integers 0 through MAX_INTS-1 would be printed in order.

...

Code Block
bgColor#CCCCFF
borderStylesolid
langc

#include <stdio.h>

typedef struct int_struct {
  int x;
} int_struct;

#define MAX_INTS 10

int main(void){
  size_t i;
  int_struct ints[MAX_INTS];

  for (i = 0; i < MAX_INTS; i++) {
    ints[i] = (int_struct){i};
  }

  for (i = 0; i < MAX_INTS; i++) {
    printf("%d\n", ints[i].x);
  }
}

...

Recommendation

Severity

Likelihood

Remediation Cost

Priority

Level

DCL21-C

low

unlikely

medium

P2

L3

Related Guidelines

ISO/IEC 9899:19992011 Section 6.5.2.5 (Compound Literals), "Compound literals"

Bibliography

...