Search code examples
clanguage-lawyer

C braced initializer for -non- array


Please consider the following absurd but compiling code:

int main(int argc, char *argv[]) {
    void *a, *b, *c, *d;

    void *the_good_array[] = { a, b, c, d };
    void *the_bad_array    = { a, b, c, d };

    return 0;
}

I accidentally produced something similar and, to my astonishment, it fully compiles.

  • Why does it compile?
  • What is { a, b, c, d } supposed to mean as an initializer for a non array? Without the braces, I would understand it's an accidental use of the , operator resulting in the value of the last element (d). But, braces? What are they supposed to mean here?

If possible, please refer to the C standard when answering.

Edit 1: Compiles with both:

gcc -std=iso9899:1990 /tmp/bad_array.c     # gcc (Debian 12.2.0-14)`
clang -std=iso9899:1990 /tmp/bad_array.c   # Debian clang version 14.0.6

Edit 2: Apparently

int i = { 0 };

is perfectly valid C.

I would like to know why but don't have the standard to read it.


Solution

  • What is { a, b, c, d } supposed to mean as an initializer for a non array?

    Having multiple intializer elements for single object is a constraint violation. N2176 (C17 standard draft) §6.7.9 Initialization:

    Constraints

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

    In this case it's depends on compiler what happens.

    Why does it compile?

    C compilers take backwards compatibility quite seriosly, and will accept a lot of code that would be considered invalid nowadays.

    But, braces? What are they supposed to mean here?

    Braces are allowed allowed even around single expression:

    Syntax

      • initializer:
        • assignment-expression
        • { initializer-list }
        • { initializer-list , }
      • initializer-list:
        • designationopt initializer
        • initializer-list , designationopt initializer
          ...

    With rules above, initializer can after a few steps be expanded to { assignment-expression }.