﻿# V2651\. MISRA\. Initializer using chained designators should not contain initializers without designators\.

This diagnostic rule is based on the [MISRA](https://misra.org.uk/) \(Motor Industry Software Reliability Association\) software development guidelines\.

This diagnostic rule is relevant only for C\.

Avoid mixing chained **designators** and positional initialization within an object aggregate initialization\. This may impair code readability or lead to unexpected issues\.

When declaring objects of structures, unions, or arrays, a programmer can provide initial values for fields or elements using **aggregate initialization** \(`{ .... }`\)\. Initializers can be of two types: **positional** and **designated**\.

Positional initializers fill:

* array elements in the order of increasing index;
* structure fields in their declaration order\.

Any array elements or structure fields lacking an explicit initializer will be zero\-initialized\. The example of positional initialization:

```cpp
typedef struct
{
  int x;
  int y;
  int z;
} TypeA;

TypeA obj = { 0, 0 }; // positional initialization
                      // obj == { 0, 0, 0 }
```

**Designated initializers** \(designators\) enable to initialize a specified array element or structure field\. The example of designated initialization:

```cpp
typedef struct
{
  int x;
  int y;
  int z;
} TypeA;

TypeA obj = { .x = 1, .y = 2 }; // designated initialization
//            ^~      ^~        // obj == { 1, 2, 0 }
//             \_____/
//           designators
```

If a positional initializer follows a designator, it initializes the next element or field after the designated one\. Look at the example:

```cpp
typedef struct
{
  int x;
  int y;
  int z;
} TypeA;

TypeA obj = { .y = 2, 3 }; // mixed aggregate initialization
                           // obj == { 0, 2, 3 }
```

If a designator consists of a compound name, it is considered \(**nested**/**chained**\) and allows initializing a subobject within a structure field or array element:

```cpp
typedef struct
{
  int x;
  int y;
} TypeA;

typedef struct
{
  TypeA a;
  double coeff;
} TypeB;

TypeB obj = { .a.x = -1, .coeff = 0.5 }; // obj == { { -1, 0 }, 0.5 }
//            ^~~~
//             \
//              nested/chained designator
```

To enhance code readability and prevent unexpected problems, avoid using chained designators and positional initializers within the same initializers level\. Look at the example with an error:

```cpp
typedef struct
{
  int x;
  int y;
} Point;

typedef struct
{
  Point      center;
  double     radius;
  int    fill_color;
} Circle;

static Circle CreateRedCircle(void)
{
  Circle res = { .center.x = 5,
                 1.0,
                 0xFF0000 };
  
  return res; // Expects res == { { 5, 0 }, 1.0, 0xFF0000 }
              //  Actual res == { { 5, (int) 1.0 },
              //                  (double) 0xFF0000,
              //                  0 }
}
```

The `CreateRedCircle` function is used to create a red circle with the center `(5; 0)`, radius `1.0`, and a red fill color\. However, due to the properties of designators described above, the object will be initialized in the following way:

1. the initializer `1.0` will be applied to the `.center.y` field, not to `.radius`;
1. the initializer `0xFF0000` will be applied to the `.radius` field, not to `.radius`;
1. the `.fill_color` field will be zero\-initialized\.

To fix the problem, use designators for every field of the object and its subobjects:

```cpp
static Circle CreateRedCircle(void)
{
  Circle res = { .center.x = 5,
                 .center.y = 0,
                 .radius = 1.0,
                 .fill_color = 0xFF0000 };
  
  return res; // Expects res == { { 5, 0 }, 1.0, 0xFF0000 }
              //  Actual res == { { 5, 0 }, 1.0, 0xFF0000 }
}
```

**Exception**\. A subobject initializer can omit designators in its own initializer list, but only if two conditions are met:

1. the subobject initializer has no chained designators;
1. no designator in the wrapping initializer list points inside this subobject\.

```cpp
static Circle CreateRedCircle(void)
{
  Circle res = { .center = { 5, 0 },
                 .radius = 1.0,
                 .fill_color = 0xFF0000 };
  
  return res; // Expects res == { { 5, 0 }, 1.0, 0xFF0000 }
              //  Actual res == { { 5, 0 }, 1.0, 0xFF0000 }
}
```