606

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.

Rafael
  • 7,605
  • 13
  • 31
  • 46
cringe
  • 13,401
  • 15
  • 69
  • 102
  • 3
    you really should accept a better answer, I see you had to use some bad coding guide, but you still shouldn't suggest to other people that that is the right way to do it.. – Karoly Horvath Jul 28 '12 at 09:43
  • @KarolyHorvath well, most of the good answers are specific to C99. Maybe my question is a duplicate of http://stackoverflow.com/questions/6624975/c90-how-do-i-globally-initialize-this-struct-in-c-without-c99-extensions ? – cringe Jul 29 '12 at 10:02
  • if that was your original intention, then probably yes, but then 1) the votes would be very misleading. 2) from the top search hits this is the only one which shows the C99 way..... it would be better to re-use this page for C99 demonstration... (apparently people started to link this page to show how to do it) – Karoly Horvath Jul 29 '12 at 11:02
  • 15
    Interesting that the accepted (and heavily upvoted) answer doesn't actually answer the question, even as originally posted. Designated initializers don't address the OP's problem, which is to *split* the declaration from the initialization. For pre-1999 C, the only real solution is to assign to each member; for C99 and later, a compound literal, as in CesarB's answer, is the solution. (Of course an actual initializer, with or without designators, would be even better, but apparently the OP was saddled with a really bad coding standard.) – Keith Thompson Jun 09 '13 at 06:39
  • 35
    Strictly speaking, the term "ANSI C" now refers to the 2011 ISO standard, which ANSI has adopted. But in practice the term "ANSI C" commonly refers to the (officially obsolete) 1989 standard. For example, "gcc -ansi" still enforces the 1989 standard. Since it's ISO that published the 1990, 1999, and 2011 standards, it's best to avoid the term "ANSI C", and to refer to the date of the standard if there's any possibility of confusion. – Keith Thompson Jun 09 '13 at 06:43
  • See also [Designated initializers and omitted elements](http://stackoverflow.com/questions/763763/designated-initializers-and-omitted-elements) for another aspect of the use of designated initializers. It isn't a duplicate of this question; it does provide useful extra information. – Jonathan Leffler Jun 18 '14 at 14:19

16 Answers16

957

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

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

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)

Jorengarenar
  • 2,705
  • 5
  • 23
  • 60
philant
  • 34,748
  • 11
  • 69
  • 112
  • 104
    awesome, thanks. you can even nest em: static oxeRay2f ray = { .unitDir = { .x = 1.0f, .y = 0.0f } }; – orion elenzil May 02 '11 at 00:00
  • 7
    This doesn't answer the question at all. OP wants to separate the initialization from the declaration. – osvein Apr 04 '18 at 20:09
  • 6
    C99 != ANSI C - So this doesn't work in C89, nor in C90. – Tim Wißmann May 13 '18 at 12:09
  • 5
    C99 **is** ANSI C, see [this](https://stackoverflow.com/questions/17206568/what-is-the-difference-between-c-c99-ansi-c-and-gnu-c) – Cutberto Ocampo Sep 21 '18 at 05:29
  • 1
    @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." – Étienne Jun 27 '19 at 08:05
  • @É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 – Cutberto Ocampo Jul 01 '19 at 16:07
  • 4
    @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". – Étienne Jul 04 '19 at 12:08
  • An odd "gotcha" I ran into is that if you don't initialize every field of everything, the compiler would call `memset` to zero the other fields. In the interest of a minimal-size executable I was building without the CRT, had no `memset`, my code wouldn't link, and it took me a while to figure out what was going on. – sidbushes Feb 16 '22 at 17:32
  • Beware, if you try this C89 or C90 you will get a nasty `error: expected an expression` – m4l490n May 06 '22 at 05:06
261

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 };
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
CesarB
  • 43,947
  • 7
  • 63
  • 86
  • 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? – Geremia Mar 24 '16 at 19:09
  • @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. – hoijui Dec 18 '17 at 07:05
  • 5
    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**. https://ideone.com/Ze3rnZ – sherrellbc Dec 28 '17 at 12:23
  • 1
    Just as a clarification on the comment from @sherrellbc above, if "initializers are used at a time other than object creation" then they are *not initializers*. Initialization takes place at the same time as definition; any value change at another time is assignment, not initialization. So a designated initializer can be used only for initialization, whereas a compound literal can only be used for assignment. The syntax is slightly different as well because the compound literal always requires a cast. – cooperised Aug 05 '23 at 10:51
  • The difference between initialization and assignment is important in the context of `const` (where assignment is not possible but initialization is) and `static` (static locals are initialized only once, at the time of creation). – cooperised Aug 05 '23 at 10:53
114

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".

starball
  • 20,030
  • 7
  • 43
  • 238
Ron
  • 1,695
  • 1
  • 19
  • 15
  • 3
    Is it possible to use variables in the initialization ? – Cyan May 20 '16 at 13:47
  • 2
    @Cyan It is for objects with automatic storage duration. See 6.7.9 13) in http://www.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. – Petr Skocik Oct 09 '16 at 11:47
  • 1
    So the only difference with C 99 is that you can't specify the designations? – Akaisteph7 Feb 24 '20 at 23:55
50

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

would do fine in C99

qrdl
  • 34,062
  • 14
  • 56
  • 86
25

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
  • 684
  • 6
  • 15
  • 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." – emersion Jun 02 '19 at 07:28
24

You've almost got it...

MY_TYPE a = { true, 15, 0.123 };

Quick search on 'struct initialize c' shows me this

Neuron
  • 5,141
  • 5
  • 38
  • 59
Kieveli
  • 10,944
  • 6
  • 56
  • 81
  • 1
    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. – cringe Dec 01 '08 at 13:26
  • 10
    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. – Kieveli Dec 01 '08 at 13:43
  • 9
    um... You have coding rules that are deliberately bad? Perhaps you should introduce the guy who wrote them to "Resource Acquisition Is Initialization" (http://en.wikipedia.org/wiki/RAII) – James Curran Dec 01 '08 at 15:10
  • 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... – cringe Dec 02 '08 at 07:12
21

Adding to All of these good answer a summary to how to initialize a structure (union and Array) in C, focused especially on the Designed Initializer.

Standard Initialization

struct point 
{
    double x;
    double y;
    double z;
}

p = {1.2, 1.3}; 

Designated Initializer

The Designated Initializer came up since the ISO C99 and is a different and more dynamic way to initialize in C when initializing struct, union or an array.

The biggest difference to standard initialization is that you don't have to declare the elements in a fixed order and you can also omit element.

From The GNU Guide:

Standard C90 requires the elements of an initializer to appear in a fixed order, the same as the order of the elements in the array or structure being initialized.

In ISO C99 you can give the elements in random order, specifying the array indices or structure field names they apply to, and GNU C allows this as an extension in C90 mode as well


Examples

1. Array Index

Standard Initialization

int a[6] = { 0, 0, 15, 0, 29, 0 };

Designated Initialization

int a[6] = {[4] = 29, [2] = 15 }; // or
int a[6] = {[4]29 , [2]15 }; // or
int widths[] = { [0 ... 9] = 1, [10 ... 99] = 2, [100] = 3 };

2. Struct or union:

Standard Initialization

struct point { int x, y; };

Designated Initialization

struct point p = { .y = 2, .x = 3 }; or
struct point p = { y: 2, x: 3 };

3. Combine naming elements with ordinary C initialization of successive elements:

Standard Initialization

int a[6] = { 0, v1, v2, 0, v4, 0 };

Designated Initialization

int a[6] = { [1] = v1, v2, [4] = v4 };

4. Others:

Labeling the elements of an array initializer

int whitespace[256] = { [' '] = 1, ['\t'] = 1, ['\h'] = 1,
                        ['\f'] = 1, ['\n'] = 1, ['\r'] = 1 };

write a series of ‘.fieldname’ and ‘[index]’ designators before an ‘=’ to specify a nested subobject to initialize

struct point ptarray[10] = { [2].y = yv2, [2].x = xv2, [0].x = xv0 };

Guides

Community
  • 1
  • 1
Federico Baù
  • 6,013
  • 5
  • 30
  • 38
17

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.
Neuron
  • 5,141
  • 5
  • 38
  • 59
r_goyal
  • 1,117
  • 1
  • 11
  • 20
  • 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. – Alan Corey Jun 13 '17 at 20:01
5

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.

Neuron
  • 5,141
  • 5
  • 38
  • 59
Alan Corey
  • 577
  • 6
  • 10
5

This can be done in different ways:

MY_TYPE a = { true, 1, 0.1 };

MY_TYPE a = { .stuff = 0.1, .flag = true, .value = 1 }; //designated initializer, not available in c++

MY_TYPE a;
a = (MY_TYPE) { true,  1, 0.1 };

MY_TYPE m (true, 1, 0.1); //works in C++, not available in C

Also, you can define member while declaring structure.

#include <stdio.h>

struct MY_TYPE
{
    int a;
    int b;
}m = {5,6};

int main()
{
    printf("%d  %d\n",m.a,m.b);    
    return 0;
}
dev
  • 649
  • 9
  • 11
3

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

Neuron
  • 5,141
  • 5
  • 38
  • 59
eddyq
  • 879
  • 1
  • 13
  • 25
3
void function(void) {
  MY_TYPE a;
  a.flag = true;
  a.value = 15;
  a.stuff = 0.123;
}
David Guyon
  • 2,759
  • 1
  • 28
  • 40
robert
  • 1,300
  • 10
  • 3
3

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.

Palec
  • 12,743
  • 8
  • 69
  • 138
4t8dds
  • 565
  • 7
  • 19
1

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;
}
tdube
  • 2,453
  • 2
  • 16
  • 25
Ajay
  • 21
  • 3
0

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);
-3

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 */
div0man
  • 321
  • 1
  • 9
  • 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. – ad absurdum Dec 02 '18 at 18:20
  • 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` – div0man Dec 02 '18 at 18:21