Question
How to Initialize a Struct in C: Declaration, Assignment, and Standard-Compliant Syntax
Question
I want to initialize a struct variable, but I want the declaration and the value setup to happen separately. Here is the code 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 a valid and standard-compliant way to declare and initialize a local variable of type MY_TYPE in C standards such as C89, C90, C99, and C11?
If not, what is the correct or preferred way to do this?
A later update mentioned using a static initializer object where each member is set explicitly.
Short Answer
By the end of this page, you will understand the difference between struct initialization and struct assignment in C, why a = { ... }; is not valid standard C syntax, and how to correctly create and populate structs using declaration-time initializers, compound literals, member-by-member assignment, or a prebuilt template value.
Concept
In C, initialization and assignment are related but different operations.
- Initialization happens when a variable is declared.
- Assignment happens after the variable already exists.
That distinction matters for structs.
Initialization at declaration
When you declare a struct variable, you can initialize it with braces:
MY_TYPE a = { true, 15, 0.123 };
This is called an initializer. It is valid C syntax.
Assignment after declaration
Once the variable has already been declared, you cannot use a bare brace initializer by itself:
MY_TYPE a;
a = { true, 15, 0.123 }; /* invalid */
That is not valid standard C.
Why?
Because { ... } by itself is not a normal expression in C. Initializer lists are used in declarations, not as standalone assignment values.
Correct ways to assign a struct later
You have a few standard-compliant options:
- Assign members one by one
MY_TYPE a;
a.flag = ;
a.value = ;
a.stuff = ;
Mental Model
Think of a struct like a filled-out paper form with several fields.
- Initialization is filling in the form at the moment you create it.
- Assignment is replacing the entire form later with another completed form.
- Member assignment is erasing and rewriting one field at a time.
The syntax { true, 15, 0.123 } is like a blank template used when creating the form. In older C rules, you cannot just hand that template directly to an already existing variable unless you wrap it as a real struct value using a compound literal in C99+.
Syntax and Examples
1. Initialize when declaring the variable
MY_TYPE a = { true, 15, 0.123 };
This is valid C initialization syntax.
2. Assign each member separately
MY_TYPE a;
a.flag = true;
a.value = 15;
a.stuff = 0.123;
This works in all common C standards.
3. Assign from another struct variable
MY_TYPE a;
MY_TYPE b = { true, 15, 0.123 };
a = b;
Struct assignment is allowed in C. The whole struct is copied.
4. Use a compound literal (C99 and later)
MY_TYPE a;
a = (MY_TYPE){ true, 15, 0.123 };
This is often the cleanest way to assign all fields at once after declaration.
5. Use designated initializers (C99 and later)
MY_TYPE a = { .flag = true, .value = 15, .stuff = 0.123 };
This is especially useful when:
Step by Step Execution
Consider this C99+ example:
#include <stdbool.h>
typedef struct {
bool flag;
short int value;
double stuff;
} MY_TYPE;
void function(void) {
MY_TYPE a;
a = (MY_TYPE){ true, 15, 0.123 };
}
Step by step
MY_TYPEis defined as a struct type with three members.- Inside
function,ais declared. - At this point,
aexists, but its members are uninitialized because it is a local automatic variable. - The expression
(MY_TYPE){ true, 15, 0.123 }creates a temporary struct value of typeMY_TYPE. - That temporary value is assigned to
ausing normal struct assignment. - After the assignment:
a.flagistrue
Real World Use Cases
Struct initialization and assignment show up in many practical C programs.
Configuration objects
typedef struct {
int port;
int debug;
} Config;
Config cfg = { 8080, 1 };
Used for program settings loaded at startup.
Returning multiple values from a function
typedef struct {
int code;
double result;
} Response;
Response make_response(void) {
return (Response){ 200, 42.5 };
}
Useful when a function needs to return related values together.
Resetting state
typedef struct {
int count;
int error;
} State;
void reset_state(State *s) {
*s = (State){ 0, 0 };
}
This is common in state machines and embedded code.
Real Codebase Usage
In real projects, developers usually choose one of a few clear patterns.
Pattern 1: Initialize immediately when possible
MY_TYPE item = { true, 15, 0.123 };
This is the simplest and safest option.
Pattern 2: Use designated initializers for readability
MY_TYPE item = {
.flag = true,
.value = 15,
.stuff = 0.123
};
This is common when structs have many fields.
Pattern 3: Use a default template and then customize
static const MY_TYPE default_item = { false, 0, 0.0 };
MY_TYPE item = default_item;
item.value = 15;
This is common in configuration-heavy code.
Pattern 4: Reset a struct with one assignment
*obj = (MY_TYPE){ 0 };
This sets all members to zero in C99+.
Pattern 5: Validate after assignment
MY_TYPE item = { true, , };
(item.value < ) {
}
Common Mistakes
Mistake 1: Using a brace initializer in assignment
MY_TYPE a;
a = { true, 15, 0.123 }; /* invalid */
Why it is wrong
A bare initializer list is not a valid assignment expression in standard C.
Fix
a = (MY_TYPE){ true, 15, 0.123 }; /* C99+ */
or
a.flag = true;
a.value = 15;
a.stuff = 0.123;
Mistake 2: Forgetting that local structs are uninitialized
MY_TYPE a;
/* using a.value here is unsafe */
Fix
Always initialize before use.
MY_TYPE a = { 0 };
Mistake 3: Using bool in C89/C90 without support
bool flag;
Comparisons
| Approach | Example | Works in C89/C90 | Works in C99/C11 | Notes |
|---|---|---|---|---|
| Declaration-time initialization | MY_TYPE a = { true, 15, 0.123 }; | Partly, but bool needs care | Yes | Standard initializer at declaration |
| Bare brace assignment | a = { true, 15, 0.123 }; | No | No | Invalid standard C |
| Member-by-member assignment | a.flag = true; | Yes | Yes | Most portable |
| Assign from another struct variable | a = b; |
Cheat Sheet
/* Struct type */
typedef struct {
bool flag;
short int value;
double stuff;
} MY_TYPE;
/* Valid: initialize at declaration */
MY_TYPE a = { true, 15, 0.123 };
/* Invalid: bare brace assignment */
MY_TYPE a;
a = { true, 15, 0.123 }; /* not standard C */
/* Valid: assign members individually */
a.flag = true;
a.value = 15;
a.stuff = 0.123;
/* Valid: assign from another struct */
MY_TYPE b = { true, 15, 0.123 };
a = b;
/* Valid in C99+: compound literal */
a = (MY_TYPE){ true, 15, 0.123 };
FAQ
Is a = {1, 2, 3}; valid in C?
No. A bare brace initializer is not valid as a normal assignment expression in standard C.
How do I assign a struct after declaration in C?
Use member-by-member assignment, assign from another struct variable, or use a compound literal in C99 and later.
What is the difference between initializing and assigning a struct?
Initialization happens when the variable is declared. Assignment happens later, after the variable already exists.
Can I copy one struct to another with = in C?
Yes. If both variables have the same struct type, = performs whole-struct assignment.
Are compound literals available in C89 or C90?
No. Compound literals were added in C99.
Can I partially initialize a struct in C?
Yes. At declaration time, omitted members are zero-initialized. In C99+, designated initializers make this clearer.
Is bool valid in all C standards?
No. bool is standard in C99 and later through stdbool.h. Older C code often uses int instead.
Mini Project
Description
Create a small C program that manages a SensorConfig struct. The goal is to practice the difference between declaration-time initialization and post-declaration assignment. You will create a default configuration, copy it into another variable, and then customize individual fields.
Goal
Build a program that creates struct values correctly using standard C syntax and prints the final configuration.
Requirements
- Define a struct with at least three fields.
- Create one default struct value using declaration-time initialization.
- Create another struct variable and assign it from the default value.
- Update at least one field after assignment.
- Print the final values to verify the result.
Keep learning
Related questions
Building More Fault-Tolerant Embedded C++ Applications for Radiation-Prone ARM Systems
Learn practical C++ and compile-time techniques to reduce soft-error damage in embedded ARM systems exposed to radiation.
C printf Format Specifier for bool: How to Print Boolean Values
Learn how to print bool values in C with printf, why no %b/%B specifier exists, and the common patterns to print true/false or 0/1.
Calling C or C++ from Python: Building Python Bindings
Learn the quickest ways to call C or C++ from Python, including ctypes, C extensions, Cython, and binding tools with practical examples.