3

I'm curious if there's a better way of changing every variable in a structure instead of the following block of code.

struct RuntimeData
{
    double runtime_ms, sum_ms, avg_time_ms, best_time_ms;
};

int main()
{
    struct RuntimeData selection;

    // The '0' values are just for example..
    selection.runtime_ms = 0;
    selection.sum_ms = 0;
    selection.avg_time_ms = 0;
    selection.best_time_ms = 0;
}

I'd much rather be able to do something similar to this...

struct RuntimeData selection;

selection = { .runtime_ms=0,
              .sum_ms = 0,
              .avg_time_ms = 0,
              .best_time_ms = 0
};

...or something similar. I know you can do the latter codeblock while initializing the structure, but it results in a compilation error after the struct has already been initialized.

EDIT: Using Nate's and Vlad's answers, a compound literal is exactly what I needed! Thank you so much.

  • There's always everyone's old pal `bzero()` or `memset()`. – tadman Feb 14 '20 at 23:22
  • With designated initializers, you only need to set the non-zero values, and the rest will get zero-initialized. – jxh Feb 14 '20 at 23:34
  • 1
    I just can’t understand what is wrong the first example. – Fredrik Feb 14 '20 at 23:51
  • 1
    FYI, the things inside structures are preferably called “members,” not “variables.” – Eric Postpischil Feb 14 '20 at 23:55
  • 2
    @Fredrik Nothing is inherently "wrong" with it, at least not functionally. I was just curious if there was a cleaner way to write it for the human eye. Notice how using a compound literal separates the selection structure more clearly and prevents visual clutter. – Noah Mutersbaugh Feb 15 '20 at 00:03

4 Answers4

3

You can use a compound literal:

struct RuntimeData selection;

void foo(void) {
  selection = (struct RuntimeData){ 0, 0, 0, 0 };
}

This can be combined with designated initializers:

struct RuntimeData selection;

void foo(void) {
  selection = (struct RuntimeData){ 
                    .sum_ms = 42.3,
                    .avg_time_ms = 123.4,
                    .best_time_ms = -7e17,
                    .runtime_ms = 0.0001 
  };
}
Nate Eldredge
  • 48,811
  • 6
  • 54
  • 82
2

You can use the compound literal. Here you are.

#include <stdio.h>

struct RuntimeData
{
    double runtime_ms, sum_ms, avg_time_ms, best_time_ms;
};

int main(void) 
{
    struct RuntimeData selection = 
    { 
        .runtime_ms=0,
        .sum_ms = 0,
        .avg_time_ms = 0,
        .best_time_ms = 0
    };

    {
        selection = ( struct RuntimeData )
        { 
            .runtime_ms=1,
            .sum_ms = 1,
            .avg_time_ms = 1,
            .best_time_ms = 1
        };
    }

    printf( "%.1f, %.1f, %.1f, %.1f\n ", 
            selection.runtime_ms, 
            selection.sum_ms, 
            selection.avg_time_ms,
            selection.best_time_ms );

    return 0;
}

The program output is

1.0, 1.0, 1.0, 1.0

Of course you can simplify the compound literal the following way

selection = ( struct RuntimeData ) { 1, 1, 1, 1 };

I enclosed the assignment in braces to make shorter the life-time of the compound literal.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
2

You need a compound literal:

struct RuntimeData selection = /* Initialization with designated initializers */
    {
        .runtime_ms   = 0,
        .sum_ms       = 0,
        .avg_time_ms  = 0,
        .best_time_ms = 0
    };

selection = (struct RuntimeData){     /* Assignment of compound literal */
              .runtime_ms   = 23,
              .sum_ms       = 34,
              .avg_time_ms  = 45,
              .best_time_ms = 56
           };

Formatting is up to you. The syntax should work in C18, C11 or C99 — compound literals were not a part of C90 (aka C89). However, since the same comments apply to designated initializers and you're already using them, this won't be a problem for you.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
1

You can do the initialization with a compound literal.

selection = (struct RunTimeData){0,0,0,0};
dbush
  • 205,898
  • 23
  • 218
  • 273