Structures in C
,

Master Structures in C – A Beginner’s Guide with Interview Questions (2025)

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:

CompilerEmpty 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 4
  • short (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:

MemberSizeOffsetNotes
a1 B0
padding3 B1-3for alignment
b4 B4-7aligned on 4-byte boundary

How to Minimize Padding?

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

  1. 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?

PurposeBenefit
Simplify complex typesMakes code readable and reduces clutter
Increase portabilityAbstracts platform-dependent types (e.g., typedef int int32_t)
Easier maintenanceUpdate one typedef instead of multiple changes in code
Used with structsGives 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:

FeatureDescription
Keywordtypedef
PurposeRename/alias a data type
UsageUseful with structs, complex pointers
BenefitImproves 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 bit
  • b uses 2 bits
  • c 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:

SyntaxMeaning
ptr->memberShortcut to access
(*ptr).memberLonger 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

  1. What is a structure in C?
  2. What are the advantages of using structures?
  3. How do you declare and access a structure member?
  4. What is the difference between structure and array?
  5. Can we initialize members inside the structure?

Intermediate Level

  1. How can you pass a structure to a function?
  2. What is the difference between . and -> operators?
  3. Explain nested structures with an example.
  4. What is the size of an empty structure?
  5. Can a structure contain another structure?

Advanced/Embedded Level

  1. How is memory aligned in structures?
  2. How to minimize structure padding in embedded C?
  3. Can a structure contain a pointer to itself?
  4. Explain structure packing using #pragma pack.
  5. How are structures used in embedded register mapping?
  6. What is structure padding and how can you avoid it?
  7. Why does the compiler insert padding bytes in a structure?
  8. What are bit fields and where are they used?
  9. Can we take the address of a bit field? Why or why not?
  10. Explain structure pointers and -> operator.
  11. How are structure pointers useful in embedded system programming?
  12. What happens when you use #pragma pack(1)?
  13. Can we dynamically allocate memory for a structure?
  14. How can structure padding affect data sent over network or stored in file?
  15. 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

FeatureStructure
Custom Data TypeYes
Mixed Data TypesYes
Can be nestedYes
Dot and Arrow AccessYes
Memory EfficientWith alignment
Real-world use casesSystem-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 

Special thanks to @mr-raj for contributing to this article on EmbeddedPrep

Leave a Reply

Your email address will not be published. Required fields are marked *