Structures in C : Unlock the power of structures in C programming with this beginner-friendly guide tailored for 2025 tech interviews! Whether you’re new to C or brushing up for embedded and systems programming interviews, this post offers a clear and practical explanation of structures — from basic syntax to advanced concepts like structure padding, bit-fields, and pointers to structures.
Dive deep into real-world examples, memory layout illustrations, and commonly asked interview questions that help you build a strong foundation and gain confidence in handling Structures data in C.
What You’ll Learn:
- What is a structure and why it’s used in C
- How to define, initialize, and access structure members
- Structure padding and memory alignment
- Bit-fields and their practical usage
- Structure pointers and dynamic memory allocation
- Array of structures and nested structures
- Top interview questions and expert tips
Perfect for students, job-seekers, and professionals aiming to master data organization in C, this guide equips you with everything you need to ace interviews and write better, cleaner C code.
What is a Structure in C?
A structure is a user-defined data type that allows combining variables of different types under one name. Each variable inside a structure is called a member of the structure.
Syntax:
struct StructureName {
dataType member1;
dataType member2;
...
};
Example:
#include <stdio.h>
struct Student {
int id;
char name[50];
float marks;
};
int main() {
struct Student s1 = {1, "John", 87.5};
printf("ID: %d\n", s1.id);
printf("Name: %s\n", s1.name);
printf("Marks: %.2f\n", s1.marks);
return 0;
}
Key Concepts:
Declaration
You can declare a structure type and create variables:
struct Employee {
int emp_id;
float salary;
} e1, e2;
Accessing Structure Members
Use the dot (.
) operator:
e1.emp_id = 101;
e1.salary = 50000.00;
Structure Pointer and Arrow (->
) Operator
struct Employee *ptr = &e1;
ptr->salary = 55000.00;
Nested Structures
struct Date {
int day, month, year;
};
struct Employee {
int id;
struct Date joiningDate;
};
Array of Structures
struct Student students[5];
Why Use Structures?
- To group logically related data
- To create complex data models
- To make code more readable and maintainable
- Crucial for hardware register mapping in embedded C
Memory Layout of Structures
Structure members are stored sequentially in memory, and padding may be added for alignment. You can control this using #pragma pack
(compiler-specific).
Important Notes:
- You can’t initialize members inside the struct definition.
- Structures can’t contain functions, but they can contain function pointers.
sizeof(struct)
returns the size including padding bytes.- You can pass structure to functions by value or pointer.
What is the size of a structure in C if nothing is defined inside it?
In Standard C:
In standard C (C89/C90 and later), a structure must contain at least one member. An empty structure is not allowed and will typically give a compiler error.
Example:
struct Empty {
// nothing inside
};
int main() {
struct Empty e;
printf("%lu", sizeof(e));
return 0;
}
Output (for most compilers like GCC):
error: structure has no members
In GNU C (GCC) – Extension:
GCC does allow empty structures as a compiler extension (used sometimes in low-level code or placeholders). In such cases:
- The size of an empty struct is typically 1 byte, to ensure each variable has a unique address.
✔️ Example (GCC):
struct Empty { };
int main() {
struct Empty e;
printf("%zu\n", sizeof(e)); // Output: 1
return 0;
}
Why 1 byte?
This is done to ensure that even an empty structure occupies a unique memory location (not zero bytes), which is important for things like:
- Arrays of structures
- Memory alignment
- Pointers
Summary Table:
Compiler | Empty struct allowed? | sizeof(struct) |
---|---|---|
GCC | ✅ (extension) | 1 byte |
Clang | ✅ (extension) | 1 byte |
MSVC | ❌ (error) | Compilation error |
Standard C | ❌ (not allowed) | Compilation error |
Interview Tip:
Q: What is the size of an empty structure in C?
A: In standard C, empty structures are not allowed and give a compile-time error. But in GCC (as an extension), it is allowed and the size is 1 byte.
Structure Padding in C
What is Padding?
Padding is the process of adding unused memory (bytes) between structure members to align data in memory according to the CPU architecture’s alignment requirements.
Why is Padding Needed?
Most processors access data faster when it’s aligned to its natural boundary:
int
(4 bytes) should be stored at addresses divisible by 4short
(2 bytes) at addresses divisible by 2, etc.
To maintain this alignment, compilers insert padding bytes between structure members.
Example of Padding:
#include <stdio.h>
struct A {
char a; // 1 byte
int b; // 4 bytes
};
int main() {
printf("Size of struct A: %lu\n", sizeof(struct A));
return 0;
}
Output:
Size of struct A: 8
Explanation:
Member | Size | Offset | Notes |
---|---|---|---|
a | 1 B | 0 | |
padding | 3 B | 1-3 | for alignment |
b | 4 B | 4-7 | aligned on 4-byte boundary |
How to Minimize Padding?
- Reorder members from largest to smallest:
struct B {
int b; // 4 bytes
char a; // 1 byte
};
➡️ sizeof(struct B)
will be 8, but more efficient than previous layout.
- Use
#pragma pack(1)
to disable padding (GCC-specific):
#pragma pack(1)
struct Packed {
char a;
int b;
};
#pragma pack()
But be careful—disabling padding can cause slower access or alignment faults on some hardware (especially embedded/ARM CPUs).
What is typedef
in C?
typedef
is a keyword in C (and C++) used to create a new alias (name) for an existing data type. It helps in making code more readable, portable, and easier to maintain.
Syntax:
typedef existing_type new_type_name;
Basic Example:
typedef unsigned int uint;
uint a = 10; // Same as: unsigned int a = 10;
Here, uint
is a new name (alias) for unsigned int
.
Why Use typedef
?
Purpose | Benefit |
---|---|
Simplify complex types | Makes code readable and reduces clutter |
Increase portability | Abstracts platform-dependent types (e.g., typedef int int32_t ) |
Easier maintenance | Update one typedef instead of multiple changes in code |
Used with structs | Gives simple names to struct types without needing struct every time |
Common Use with struct
:
struct Student {
int id;
char name[50];
};
typedef struct Student Student;
Now you can just write:
Student s1;
Instead of:
struct Student s1;
Or even more compact:
typedef struct {
int id;
char name[50];
} Student;
With Pointers:
typedef int* IntPtr;
IntPtr p1, p2; // Both p1 and p2 are int pointers
Common Mistake:
typedef int* IntPtr;
IntPtr a, b;
Many think both a
and b
are int*
, but they are. This is correct.
But if written as:
int* a, b; // a is int*, b is int (confusing)
This is why typedef helps avoid confusion.
Summary:
Feature | Description |
---|---|
Keyword | typedef |
Purpose | Rename/alias a data type |
Usage | Useful with structs, complex pointers |
Benefit | Improves code clarity and maintainability |
Bit Fields in Structures
What Are Bit Fields?
Bit fields allow you to allocate specific number of bits to structure members instead of full bytes.
Syntax:
struct Flags {
unsigned int a : 1;
unsigned int b : 2;
unsigned int c : 5;
};
a
uses 1 bitb
uses 2 bitsc
uses 5 bits
This is useful in:
- Embedded systems (e.g., setting hardware registers)
- Flag control
- Memory optimization
Example:
#include <stdio.h>
struct Status {
unsigned int error : 1;
unsigned int ready : 1;
unsigned int mode : 2;
};
int main() {
struct Status s = {1, 0, 2};
printf("Size of Status: %lu\n", sizeof(s));
return 0;
}
Output:
Size of Status: 4
Even though total bits = 1 + 1 + 2 = 4 bits, size is still rounded to nearest word size (here: 4 bytes on 32-bit machine).
Rules and Notes:
- Bit fields must be of integer type
- You can’t take address of bit field
- Compiler decides bit packing and alignment
- Use
unsigned int
to avoid sign extension issues
Structure Pointers
What is a Structure Pointer?
A pointer to a structure stores the address of a structure variable. This is useful for:
- Passing structures efficiently to functions
- Dynamic memory allocation
- Embedded register access
Example:
#include <stdio.h>
struct Student {
int id;
char name[20];
};
int main() {
struct Student s = {101, "John"};
struct Student *ptr = &s;
printf("ID: %d\n", ptr->id); // OR (*ptr).id
printf("Name: %s\n", ptr->name);
return 0;
}
Access Operators:
Syntax | Meaning |
---|---|
ptr->member | Shortcut to access |
(*ptr).member | Longer version |
Both work the same.
Use in Dynamic Memory:
struct Student *ptr = malloc(sizeof(struct Student));
ptr->id = 10;
strcpy(ptr->name, "Alice");
Real-World Use Case: Register Mapping in Embedded C
#define UART0_BASE 0x4000C000
struct UART {
volatile uint32_t DR;
volatile uint32_t SR;
};
#define UART0 ((struct UART *)UART0_BASE)
Now you can write:
UART0->DR = 0x55;
Interview Questions on Structures in C
Beginner Level
- What is a structure in C?
- What are the advantages of using structures?
- How do you declare and access a structure member?
- What is the difference between structure and array?
- Can we initialize members inside the structure?
Intermediate Level
- How can you pass a structure to a function?
- What is the difference between
.
and->
operators? - Explain nested structures with an example.
- What is the size of an empty structure?
- Can a structure contain another structure?
Advanced/Embedded Level
- How is memory aligned in structures?
- How to minimize structure padding in embedded C?
- Can a structure contain a pointer to itself?
- Explain structure packing using
#pragma pack
. - How are structures used in embedded register mapping?
- What is structure padding and how can you avoid it?
- Why does the compiler insert padding bytes in a structure?
- What are bit fields and where are they used?
- Can we take the address of a bit field? Why or why not?
- Explain structure pointers and
->
operator. - How are structure pointers useful in embedded system programming?
- What happens when you use
#pragma pack(1)
? - Can we dynamically allocate memory for a structure?
- How can structure padding affect data sent over network or stored in file?
- Can a struct contain a pointer to itself? What is a self-referential structure?
Sample Embedded Interview Scenario
struct UART_Registers {
volatile uint32_t DR;
volatile uint32_t SR;
volatile uint32_t CR;
};
#define UART1 ((struct UART_Registers *) 0x40011000)
Question: What does this code do?
✅ Answer: It defines a structure for UART registers and maps it to the memory-mapped I/O address 0x40011000
.
Summary
Feature | Structure |
---|---|
Custom Data Type | Yes |
Mixed Data Types | Yes |
Can be nested | Yes |
Dot and Arrow Access | Yes |
Memory Efficient | With alignment |
Real-world use cases | System-level data modeling, embedded register mapping |
📘 Practice Task
Create a structure to store employee details (name, id, department, salary), and write a C program to:
- Read data of 5 employees
- Print details of the highest-paid employee
You can also Visit other tutorials of Embedded Prep
- Structure with Pointers
- Master How to Use a Saleae Logic Analyzer with Arduino Uno (2025)
- Top 30+ I2C Interview Questions
- Bit Manipulation Interview Questions
- Structure and Union in c
- Fault Handling in Arm Cortex Mx Processor
- Merge sort algorithm
Special thanks to @mr-raj for contributing to this article on EmbeddedPrep
Leave a Reply