3

For example, given a structure S:

typedef struct {
  int a, b;
} S;

... and a method which takes a pointer to S, can I assign it the value of an aggregate initializer1 all in one line? Here's my existing solution which uses a temporary:

void init_s(S* s) {
  S temp = { 1, 2 };
  *s = temp;
}

I'm using C11.


1 For the very rare super-pedant who doesn't understand my question because somehow "aggregate initializer" wouldn't apply here because the LHS is not declaring a new object, I mean "aggregate-initializer-like syntax with the braces and stuff".

BeeOnRope
  • 60,350
  • 16
  • 207
  • 386
  • 1
    Yes: `*s = (S){1,2};` See C11 n1570, § 6.5.2.5 *Compound literals*, paragraph 10: EXAMPLE 3: `drawline((struct point){.x=1, .y=1}, (struct point){.x=3, .y=4});` – Iwillnotexist Idonotexist Jul 24 '17 at 21:59
  • @IwillnotexistIdonotexist - it [works](https://godbolt.org/g/SFhL3z), thanks! Good enough for an answer :) – BeeOnRope Jul 24 '17 at 22:03
  • `*s = …` is not an initialiser. As `s` is already declared, you cannot use an initialiser at all. The code above does **not** compile. – too honest for this site Jul 24 '17 at 22:23
  • @Olaf - right, I was careful to say "_assign the result of_ an aggregrate-initializer" and so on throughout the question, so make it clear that I'm talking about assignment. If I missed a place, let me know. The code above compiles for me. – BeeOnRope Jul 24 '17 at 22:26
  • @BeeOnRope: "assign the result of an aggregrate-initializer" does not make any sense. You cannot assign an initialiser (a definition with an initialiser is not an assignment, the `=` is just the same symbol). An initialiser has no result either. What you do is simple assign the value of one `struct` object to another. – too honest for this site Jul 24 '17 at 22:35

1 Answers1

5

Yes, you can using the compound literals syntax:

#include <stdio.h>

typedef struct {
  int a, b;
} S;

int main(void) {
    S s;
    S *p = &s;

    *p = (S){1,2};

    printf("%d %d\n", p->a, p->b);
    return 0;
}

Demo

Eugene Sh.
  • 17,802
  • 8
  • 40
  • 61
  • If the compound literal is not intended to be modified, it better be a `static const`. Otherwise there might be two copy operations involved (depends on how smart the compiler is). – too honest for this site Jul 24 '17 at 22:38
  • At least for this toy example, clang and gcc get it right, generating the same [code](https://godbolt.org/g/HzNhgP) for both the compound literal assignment and a version which assigns the fields explicitly (and they are both clever enough to combine the two 32-bit constants into a 64-bit one and assign it all at once). `icc` generates the same code if `a` and `b` are parameters, but in the constant case it does it differently: creating a constant (S){1, 2} object in the `.rodata` section from which it loads. That might be smart for large constants repeatedly used, but seems wrong here. – BeeOnRope Jul 24 '17 at 23:59