4

The C18 Standard states at 6.7.9/2 that:

No initializer shall attempt to provide a value for an object not contained within the entity being initialized.

It is not really clear what it means. There is a related topic: Incosistent gcc diagnostic for string initialization. The clause I cited was used to explain the error produced by the following initialization:

//error: excess elements in array initializer char a[5]
char a[5] = {'h','e','l','l','o','\0'}; 

Where the initializer-list has length exceeding the size of the array being initialized.

But consider more trivial example:

int main(void){
    int a;
    int b = (a = 3);
}

The initializer here is (a = 3) which is an assignment-expression. And the initializer assigns a value to another object which should cause constraint-violation.

Why isn't any diagnostic printed?

St.Antario
  • 26,175
  • 41
  • 130
  • 318

1 Answers1

5

That's not "providing a value for a". It's an expression with a side effect of storing a value in a. "Providing a value" should be understood in the context of the initialization; it's not phrasing used for assignments.

A less trivial example of what the language in the standard is trying to get at might be:

struct {
    char a[4];
    char b[4];
} foo = { { 'h', 'e', 'l', 'l', 'o' } };

whereas (I think; correct me if I'm wrong) the following would be valid, albeit confusing, C:

struct {
    char a[4];
    char b[4];
} foo = { 'h', 'e', 'l', 'l', 'o' };
R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
  • 3
    Yes, the latter is valid too. And so are ugly things like `{ { 'h', 'e', 'l', 'l' }, 'o' };` – Antti Haapala -- Слава Україні Aug 11 '19 at 17:26
  • @AnttiHaapala You example exploits the ability of omitting `{` and `}` if an `initializer-list` consists of the only 1 element, right? – St.Antario Aug 11 '19 at 17:31
  • Another even worse example would be `{ { 'h', 'e', 'l'}, 'l' , 'o' };` – Antti Haapala -- Слава Україні Aug 11 '19 at 17:35
  • @AnttiHaapala `6.7.9/20`: _only enough initializers from the list are taken to account for the elements or members of the subaggregate or the first member of the contained union; any remaining initializers are left to initialize the next element or member of the aggregate of which the current subaggregate or contained union is a part_ Is that what you used? – St.Antario Aug 11 '19 at 17:44
  • @St.Antario that for R.'s second excerpt. – Antti Haapala -- Слава Україні Aug 11 '19 at 17:45
  • @AnttiHaapala Can't we use the `6.7.9/20` for `{ { 'h', 'e', 'l'}, 'l' , 'o' };` too? The first array of the `struct` is initialized with `{'h', 'e', 'l'}`, the initializer for the second array does not start with `{` so only enough elements are used (`lo\0\0`). Btw `-Wall` warns about such an initialization. – St.Antario Aug 11 '19 at 17:54
  • @AnttiHaapala A bit extending your example I tried the following: `struct str{ char a[4]; char b[4]; char c[4]; char d[4]};`. Applying the `6.7.9/20` I expected the following to work fine: `struct str foo = { {'h', 'e'}, 'l', 'l', 'o', 'w', 'o', 'r', {'l', 'd'} };`, and `foo.c` would be initialized with (`or\0\0`), but `warning: braces around scalar initializer` was printed. [Demo](https://coliru.stacked-crooked.com/a/6eeae0bb0a7f7a22). – St.Antario Aug 11 '19 at 18:22
  • Yes, I understood the behavior. The initialization `struct str foo = { {'h', 'e'}, 'l', 'l', 'o', 'w', 'o', 'r', 'r', 'r', {'l', 'd'} };` works ok (except it produces a warning when `-Wall` is enabled). Thx. – St.Antario Aug 11 '19 at 18:33
  • Also `int a[4] = { [5] = 3 };`. – Eric Postpischil Aug 12 '19 at 01:39