By cringe


2008-12-01 13:13:17 8 Comments

I want to initialize a struct element, split in declaration and initialization. This is what I have:

typedef struct MY_TYPE {
  bool flag;
  short int value;
  double stuff;
} MY_TYPE;

void function(void) {
  MY_TYPE a;
  ...
  a = { true, 15, 0.123 }
}

Is this the way to declare and initialize a local variable of MY_TYPE in accordance with C programming language standards (C89, C90, C99, C11, etc.)? Or is there anything better or at least working?

Update I ended up having a static initialization element where I set every subelement according to my needs.

14 comments

@PF4Public 2016-06-08 11:43:11

C programming language standard ISO/IEC 9899:1999 (commonly known as C99) allows one to use a designated initializer to initialize members of a structure or union as follows:

MY_TYPE a = { .stuff = 0.456, .flag = true, .value = 123 };

It is defined in paragraph 7, section 6.7.8 Initialization of ISO/IEC 9899:1999 standard as:

If a designator has the form
. identifier
then the current object (defined below) shall have structure or union type and the identifier shall be the name of a member of that type.

Note that paragraph 9 of the same section states that:

Except where explicitly stated otherwise, for the purposes of this subclause unnamed members of objects of structure and union type do not participate in initialization. Unnamed members of structure objects have indeterminate value even after initialization.

In GNU GCC implementation however omitted members are initialized as zero or zero-like type-appropriate value. As stated in section 6.27 Designated Initializers of GNU GCC documentation:

Omitted field members are implicitly initialized the same as objects that have static storage duration.

Microsoft Visual C++ compiler should support designated initializers since version 2013 according to official blog post C++ Conformance Roadmap. Paragraph Initializing unions and structs of Initializers article at MSDN Visual Studio documentation suggests that unnamed members initialized to zero-like appropriate values similarly to GNU GCC.

ISO/IEC 9899:2011 standard (commonly known as C11) which had superseded ISO/IEC 9899:1999 retains designated initializers under section 6.7.9 Initialization. It also retains paragraph 9 unchanged.

New ISO/IEC 9899:2018 standard (commonly known as C18) which had superseded ISO/IEC 9899:2011 retains designated initializers under section 6.7.9 Initialization. It also retains paragraph 9 unchanged.

@PF4Public 2016-06-08 11:45:03

Initially I suggested this as edit to the accepted answer, but it was rejected. Thus I post it as an answer.

@emersion 2019-06-02 07:28:06

I believe "Unnamed member" doesn't mean "omitted fields", but rather "anonymous members" such as the union in struct thing { union { char ch; int i; }; };. The standard later says: "If there are fewer initializers in a brace-enclosed list than there are elements or members of an aggregate, or fewer characters in a string literal used to initialize an array of known size than there are elements in the array,the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage duration."

@div0man 2018-12-02 17:46:09

I've been looking for a nice way to initialize my struct, and I've got to using the below (C99). This lets me initialize either a single structure or an array of structures in the same way as plain types.

typedef struct {
    char *str;
    size_t len;
    jsmntok_t *tok;
    int tsz;
} jsmn_ts;

#define jsmn_ts_default (jsmn_ts){NULL, 0, NULL, 0}

This can be used in the code as:

jsmn_ts mydata = jsmn_ts_default; /* initialization of a single struct */

jsmn_ts myarray[10] = {jsmn_ts_default, jsmn_ts_default}; /* initialization of
                                                    first 2 structs in the array */

@David Bowling 2018-12-02 18:20:24

But this does not initialize an array of structures to the default values. It initializes the first structure in the array to the values given in jsmn_ts_default, but the rest of the structures are initialized as if the array had static storage duration, which means that the members are initialized to NULL and 0. But if you change to #define jsmn_ts_default (jsmn_ts){"default", sizeof "default", NULL, 0} you will see that only the first array element gets so initialized.

@div0man 2018-12-02 18:21:28

Yes, I just came back from more testing, wanted to edit the post :) btw, same behaviour happens with int a[10] = {1}; Only the 1st element will be ==1

@Hartmut Schorrig 2018-08-12 14:10:33

I have read the Microsoft Visual Studio 2015 Documentation for Initializing Aggregate Types yet, all forms of initializing with {...} are explained there, but the initializing with dot, named ''designator'' isn't mentioned there. It does not work also.

The C99 standard chapter 6.7.8 Initialization explains the possibility of designators, but in my mind it is not really clear for complex structs. The C99 standard as pdf .

In my mind, it may be better to

  1. Use the = {0};-initialization for all static data. It is less effort for the machine code.
  2. Use macros for initializing, for example

    typedef MyStruct_t{ int x, int a, int b; } MyStruct; define INIT_MyStruct(A,B) { 0, A, B}

The macro can be adapted, its argument list can be independent of changed struct content. It is proper if less elements should be initialized. It is also proper for nested struct. 3. A simple form is: Initialize in a subroutine:

void init_MyStruct(MyStruct* thiz, int a, int b) {
  thiz->a = a; thiz->b = b; }

This routine looks like ObjectOriented in C. Use thiz, not this to compile it with C++ too!

MyStruct data = {0}; //all is zero!
init_MyStruct(&data, 3, 456);

@Ajay Parashar 2017-09-06 18:38:28

Structure in C can be declared and initialized like this:

typedef struct book
{
    char title[10];
    char author[10];
    float price;
} book;

int main() {
    book b1={"DS", "Ajay", 250.0};

    printf("%s \t %s \t %f", b1.title, b1.author, b1.price);

    return 0;
}

@Alan Corey 2016-05-12 17:14:03

I didn't like any of these answers so I made my own. I don't know if this is ANSI C or not, it's just GCC 4.2.1 in it's default mode. I never can remember the bracketing so I start with a subset of my data and do battle with compiler error messages until it shuts up. Readability is my first priority.

    // in a header:
    typedef unsigned char uchar;

    struct fields {
      uchar num;
      uchar lbl[35];
    };

    // in an actual c file (I have 2 in this case)
    struct fields labels[] = {
      {0,"Package"},
      {1,"Version"},
      {2,"Apport"},
      {3,"Architecture"},
      {4,"Bugs"},
      {5,"Description-md5"},
      {6,"Essential"},
      {7,"Filename"},
      {8,"Ghc-Package"},
      {9,"Gstreamer-Version"},
      {10,"Homepage"},
      {11,"Installed-Size"},
      {12,"MD5sum"},
      {13,"Maintainer"},
      {14,"Modaliases"},
      {15,"Multi-Arch"},
      {16,"Npp-Description"},
      {17,"Npp-File"},
      {18,"Npp-Name"},
      {19,"Origin"}
    };

The data may start life as a tab-delimited file that you search-replace to massage into something else. Yes, this is Debian stuff. So one outside pair of {} (indicating the array), then another pair for each struct inside. With commas between. Putting things in a header isn't strictly necessary, but I've got about 50 items in my struct so I want them in a separate file, both to keep the mess out of my code and so it's easier to replace.

@Victor Signaevskyi 2017-05-19 10:22:03

There were no question about initialization of array of structures! I mean, your answer contains overhead.

@Alan Corey 2017-06-13 19:36:55

I guess my point was declaring the struct with values already in it vs. using = to set each value later.

@Alan Corey 2017-06-13 19:44:53

That principle applies whether it's one struct or an array of them. Using = isn't really initialization, I wouldn't think.

@MichaelWang 2015-12-04 03:15:55

I found another way to initialize structs.

The struct:

typedef struct test {
    int num;
    char* str;
} test;

Initialization:

test tt = {
    num: 42,
    str: "nice"
};

As per GCC’s documentation, this syntax is obsolete since GCC 2.5.

@philant 2008-12-01 13:39:37

In (ANSI) C99, you can use a designated initializer to initialize a structure:

MY_TYPE a = { .flag = true, .value = 123, .stuff = 0.456 };

Edit: Other members are initialized as zero: "Omitted field members are implicitly initialized the same as objects that have static storage duration." (https://gcc.gnu.org/onlinedocs/gcc/Designated-Inits.html)

@orion elenzil 2011-05-02 00:00:53

awesome, thanks. you can even nest em: static oxeRay2f ray = { .unitDir = { .x = 1.0f, .y = 0.0f } };

@osvein 2018-04-04 20:09:57

This doesn't answer the question at all. OP wants to separate the initialization from the declaration.

@twity1337 2018-05-13 12:09:58

C99 != ANSI C - So this doesn't work in C89, nor in C90.

@Cutberto Ocampo 2018-09-21 05:29:49

C99 is ANSI C, see this

@Étienne 2019-06-27 08:05:42

@CutbertoOcampo your comment is not clear, the link you point to states that ANSI C is C89. It even states "Please note that since 1989, ANSI haven't had anything to do with the C language. Programmers still speaking about "ANSI C" generally haven't got a clue about what it means. ISO "owns" the C language, through the standard ISO 9899."

@Cutberto Ocampo 2019-07-01 16:07:22

@Étienne, agreed, technically they're not the same. However, in terms of what was being discussed by @ twity1337 (i.e. versions/standardization) I stand by my comment

@Étienne 2019-07-04 12:08:30

@CutbertoOcampo I understand what happened now. The original question was asking for solutions in ANSI C, obviously he wanted answers for C89 only. In 2016 the question was edited and "ANSI C" was removed, which now makes it hard to understand why this answer and comments mention "(ANSI) C99".

@r_goyal 2013-09-04 09:37:18

as Ron Nuni said:

typedef struct Item {
    int a;
    float b;
    char* name;
} Item;

int main(void) {
    Item item = {5, 2.2, "George"};
    return 0;
}

An important thing to remember: at the moment you initialize even one object/variable in the struct, all of its other variables will be initialized to default value.

If you don't initialize the values in your struct (i.e. if you just declare that variable), all variable.members will contain "garbage values", only if the declaration is local!

If the declaration is global or static (like in this case), all uninitialized variable.members will be initialized automatically to:

  • 0 for integers and floating point
  • '\0' for char (of course this is just the same as 0, and char is an integer type)
  • NULL for pointers.

@Alan Corey 2017-06-13 20:01:02

Interesting about the local/global, this also applies to struct tm time values. I had a local one and in one case DST was on, in another it wasn't, not due to anything I did. I wasn't using DST (the tm_isdst field), this was from strptime, but when I converted to time_t some were an hour off.

@robert 2008-12-01 13:19:49

void function(void) {
  MY_TYPE a;
  a.flag = true;
  a.value = 15;
  a.stuff = 0.123;
}

@detly 2011-06-23 02:28:16

Will this work if one of the fields is qualified const?

@Hayri Uğur Koltuk 2012-03-12 14:34:21

once i've heard 'initialization is different than assignment'. so isn't this an assignment rather than initialization?

@Ron Nuni 2013-06-09 03:51:57

I see you've already received an answer about ANSI C 99, so I'll throw a bone about ANSI C 89. ANSI C 89 allows you to initialize a struct this way:

typedef struct Item {
    int a;
    float b;
    char* name;
} Item;

int main(void) {
    Item item = { 5, 2.2, "George" };
    return 0;
}

An important thing to remember, at the moment you initialize even one object/ variable in the struct, all of its other variables will be initialized to default value.

If you don't initialize the values in your struct, all variables will contain "garbage values".

Good luck!

@Cyan 2016-05-20 13:47:29

Is it possible to use variables in the initialization ?

@PSkocik 2016-10-09 11:47:55

@Cyan It is for objects with automatic storage duration. See 6.7.9 13) in open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf . For global objects is pretty much restricted to literals. You can't even use other global objects, even if they're const.

@eddyq 2014-04-20 19:39:46

If MS has not updated to C99, MY_TYPE a = { true,15,0.123 };

@CesarB 2008-12-01 13:28:09

You can do it with a compound literal. According to that page, it works in C99 (which also counts as ANSI C).

MY_TYPE a;

a = (MY_TYPE) { .flag = true, .value = 123, .stuff = 0.456 };
...
a = (MY_TYPE) { .value = 234, .stuff = 1.234, .flag = false };

The designations in the initializers are optional; you could also write:

a = (MY_TYPE) { true,  123, 0.456 };
...
a = (MY_TYPE) { false, 234, 1.234 };

@Geremia 2016-03-24 19:09:47

So, designated initializers are for when you declare and define at the same time, but compound literals are for when you define an already-declared variable?

@hoijui 2017-12-18 07:05:45

@Geremia you have to first define the struct in both cases, but with designated initializers, you make the code more readable, and more resilient to errors, in case of changes in the struct.

@sherrellbc 2017-12-28 12:23:50

This is a little tricky. Many times (some successful) I have tried to use designated initializers. However, it only has now become clear (thanks to your and @philant's example) that there must exist a cast if the initializer is not used at the time of object creation. However, I have now also learned that if initializers are used at a time other than object creation (as in your example) then it is referred to as a compound literal, not strictly a designated initializer. ideone.com/Ze3rnZ

@qrdl 2008-12-01 13:27:22

a = (MYTYPE){ true, 15, 0.123 };

would do fine in C99

@Kieveli 2008-12-01 13:21:54

You've almost got it...

MY_TYPE a = { true,15,0.123 };

Quick search on 'struct initialize c' shows me this

@cringe 2008-12-01 13:26:25

I think this is true for standard C, but not for ANSI C(99?). Also I'm bound to coding rules that won't allow me to do declaration and initialization at once, so I have to split it up and initialize every single subelement.

@Kieveli 2008-12-01 13:43:25

Initialization can only happen at the point of declaration. That is what it means to 'initialize'. Otherwise you're allowing an undefined value to be the inital value of your variable / struct, and then assigning a value later.

@James Curran 2008-12-01 15:10:34

um... You have coding rules that are deliberately bad? Perhaps you should introduce the guy who wrote them to "Resource Acquisition Is Initialization" (en.wikipedia.org/wiki/RAII)

@cringe 2008-12-02 07:12:59

Trust me, I really, really, can't change a bit of this rules at this point. It feels horrible to code it. And there are a lot of other rules right out of the 70s, like static code headers with management information like Revision number. Changes for every release, even if the source didn't change...

Related Questions

Sponsored Content

14 Answered Questions

[SOLVED] How to print struct variables in console?

  • 2014-07-01 13:57:18
  • fnr
  • 227796 View
  • 289 Score
  • 14 Answer
  • Tags:   struct go

9 Answered Questions

[SOLVED] Initialize/reset struct to zero/null

23 Answered Questions

[SOLVED] How to initialize HashSet values by construction?

10 Answered Questions

[SOLVED] How to initialize an array in Java?

21 Answered Questions

[SOLVED] How to initialize all members of an array to the same value?

17 Answered Questions

[SOLVED] How to initialize private static members in C++?

3 Answered Questions

[SOLVED] Initializing a struct to 0

2 Answered Questions

[SOLVED] GCC options for strict C90 code?

  • 2014-10-22 07:28:23
  • malat
  • 2910 View
  • 13 Score
  • 2 Answer
  • Tags:   c gcc iso c89

Sponsored Content