๐Ÿ—๏ธ 14. Structures & Unions

So far, you have worked with individual values such as int, float, char, arrays and pointers.

But real programs often need to represent an entity containing different kinds of information.

For example, a student may have:

  • Student ID โ†’ int
  • Name โ†’ character array
  • Marks โ†’ float
  • Age โ†’ int

A structure lets us group these related members into one object.

A union also groups different members, but its members share the same storage.

Core idea: Use a structure for values needed together, such as a studentโ€™s ID, name, and marks. Use a union for alternatives that share storage, such as a value stored as either an integer or a floating-point number.

14.1 What Is a Structure?

A structure is a user-defined type that groups related data items, called members, under one object.

The members can have different data types.

struct Student { int id; char name[50]; float marks; };

This defines a structure type named struct Student.

It defines the fields each student record will have. A separate object declaration creates storage for a particular student.

Important: The structure definition above does not create a separate Student object by itself. It defines the type.

14.2 Why Are Structures Needed?

Suppose you want to store information about three students. Without structures, you might create separate variables:

int id1, id2, id3; char name1[50]; char name2[50]; char name3[50]; float marks1, marks2, marks3;

This becomes difficult to organize.

With structures:

struct Student students[3];

Each array element represents one complete student record.

Without Structure

Related information is scattered across separate variables.

With Structure

Related information is grouped into one meaningful object.

14.3 Structure Syntax

struct StructureName { data_type member1; data_type member2; data_type member3; };

Example:

struct Employee { int id; char name[40]; float salary; };

The keyword struct introduces a structure specification.

The name after struct is called the tag.

struct

Keyword used to define or refer to a structure.

Employee

Structure tag identifying this structure type.

Members

Variables stored inside each structure object.

14.4 Creating Structure Variables

After defining the structure type, create objects using:

struct Student s1; struct Student s2;

Now s1 and s2 are two separate structure objects.

struct Student { int id; float marks; }; int main(void) { struct Student s1; s1.id = 101; s1.marks = 85.5f; return 0; }

Structure Object

 struct Student s1 โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ id โ”‚ 101 โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ marks โ”‚ 85.5 โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ s1 is one complete Student object. Each member has its own storage. 

14.5 Accessing Structure Members with .

The dot operator . is used to access a member of a structure object.

s1.id s1.marks

Example:

#include <stdio.h>

struct Student {
    int id;
    float marks;
};
int main(void) {
    struct Student s;
    s.id = 101;
    s.marks = 92.5f;
    printf("ID = %d\n", s.id);
    printf("Marks = %.2f\n", s.marks);
    return 0;
}
Remember: structureObject.member is the normal syntax for accessing a structure member.

14.6 Initializing Structures

A structure object can be initialized when it is created.

struct Student s = {101, 85.5f};

With positional initialization, each value initializes the corresponding member in declaration order. A designated initializer names its member explicitly.

struct Student { int id; float marks; }; struct Student s = {101, 85.5f};

Therefore:

s.id โ†’ 101 s.marks โ†’ 85.5

Positional Initialization

Positional initialization follows member order.

C99 Designated Initialization

struct Student s = { .marks = 85.5f, .id = 101 };

14.7 Updating Structure Members

Structure members can be changed just like ordinary variables.

struct Student s = {101, 80.0f}; s.marks = 90.0f;

After the assignment:

s.id = 101 s.marks = 90.0

The complete structure object remains the same object; only one member is changed.

14.8 Program Tracing: Structure Members

struct Student { int id; int marks; }; int main(void) { struct Student s; s.id = 101; s.marks = 85; s.marks = s.marks + 5; return 0; }
 Step 1 struct Student s; โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ id โ”‚ ? โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ marks โ”‚ ? โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ Step 2 s.id = 101; โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ id โ”‚ 101 โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ marks โ”‚ ? โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ Step 3 s.marks = 85; โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ id โ”‚ 101 โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ marks โ”‚ 85 โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ Step 4 s.marks = s.marks + 5; โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ id โ”‚ 101 โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ marks โ”‚ 90 โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ 

14.9 Understanding the Structure Tag

struct Student { int id; float marks; };

Here Student is the structure tag.

You normally write the type as:

struct Student

not simply:

Student
Common confusion: Unlike some languages, C does not automatically create Student as a standalone type name from struct Student. The typedef mechanism can create such an alias, which is covered later.

14.10 Structure Definition vs Structure Variable

Type definition:

struct Book { int pages; float price; };

Object declaration:

struct Book b1;

The first describes the type. The second creates an object.

Both can also be written together:

struct Book { int pages; float price; } b1, b2;
The variables b1 and b2 are created by the declarators following the closing brace.

14.11 Multiple Structure Variables

struct Point { int x; int y; }; int main(void) { struct Point p1 = {10, 20}; struct Point p2 = {30, 40}; printf("%d %d\n", p1.x, p1.y); printf("%d %d\n", p2.x, p2.y); return 0; }

Changing a member of s1 does not change the corresponding member of a separate s2 object. Each structure object holds its own record.

 p1 โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ x = 10 โ”‚ โ”‚ y = 20 โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ p2 โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ x = 30 โ”‚ โ”‚ y = 40 โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ p1 and p2 are separate objects. 

14.12 Structure Assignment

Two structure objects of compatible structure type can be assigned to each other.

struct Student { int id; float marks; }; int main(void) { struct Student s1 = {101, 85.0f}; struct Student s2; s2 = s1; printf("%d %.2f\n", s2.id, s2.marks); return 0; }

The member values are copied, including the elements of an array member. A character array inside the structure therefore gets its own copied characters.

A pointer member is different: assignment copies its pointer value, not the object it points to. Both copied pointers may refer to the same allocation. Copy that allocation separately if the records need independent ownership.

14.13 Can We Compare Structures with ==?

C does not provide direct == or != operators for comparing complete structure objects.

Compare the fields that define equality for your application. Compare a character-array name with strcmp, not ==. Do not use memcmp as a general replacement: padding bytes can differ even when member values compare equal.

if (s1.id == s2.id && s1.marks == s2.marks) { printf("Same selected values"); }
Do not write: if (s1 == s2) for ordinary C structure objects.

14.14 Nested Structures

A structure can contain another structure as a member.

struct Date { int day; int month; int year; }; struct Student { int id; struct Date dob; };

Access nested members using multiple dot operators:

student.dob.day student.dob.month student.dob.year

Example:

struct Student s = { 101, {15, 8, 2004} }; printf("%d\n", s.dob.year);

Output:

2004

14.15 Array of Structures

An array of structures stores several complete records. For example, students[2].marks is the marks member of the third student, because array indexes start at zero.

struct Student { int id; float marks; }; struct Student students[3];

Access an element and its member using:

students[0].id students[0].marks students[1].id students[1].marks

Example

#include <stdio.h>

struct Student {
    int id;
    int marks;
};
int main(void) {
    struct Student students[3] = {
        {
            101, 78
        }, {
            102, 91
        }, {
            103, 84
        }
    };
    for (int i = 0; i < 3; i++) {
        printf("ID = %d, Marks = %d\n", students[i].id, students[i].marks);
    }
    return 0;
}
 students Index 0 โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ id = 101 โ”‚ โ”‚ marks = 78 โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ Index 1 โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ id = 102 โ”‚ โ”‚ marks = 91 โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ Index 2 โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ id = 103 โ”‚ โ”‚ marks = 84 โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ 

14.16 Structures with Functions

A structure can be passed to a function just like other values.

#include <stdio.h>

struct Student {
    int id;
    float marks;
};
void display(struct Student s) {
    printf("ID = %d\n", s.id);
    printf("Marks = %.2f\n", s.marks);
}
int main(void) {
    struct Student s = {
        101, 88.5f
    };
    display(s);
    return 0;
}

Here the structure is passed by value.

The function receives its own parameter object containing the copied structure value.

14.17 Passing a Structure by Value

struct Point { int x; int y; }; void change(struct Point p) { p.x = 100; } int main(void) { struct Point point = {10, 20}; change(point); printf("%d\n", point.x); return 0; }

The output remains:

10

Why?

The parameter is a separate structure object. Changing its ordinary members changes only that copy. A copied pointer member can still be used to reach shared data, so distinguish the member from its target.

This follows the same pass-by-value rule discussed in the Functions topic.

14.18 Passing a Structure Using a Pointer

If a function needs to modify the original structure, pass its address.

#include <stdio.h>

struct Student {
    int id;
    int marks;
};
void updateMarks(struct Student *p) {
    p->marks = 95;
}
int main(void) {
    struct Student s = {
        101, 80
    };
    updateMarks(&s);
    printf("Marks = %d\n", s.marks);
    return 0;
}

Output:

Marks = 95

The pointer allows the function to access the original structure object.

14.19 The -> Operator

When you have a pointer to a structure, use -> to access its members.

p->marks

This is equivalent to:

(*p).marks
 struct Student s = {101, 85}; struct Student *p = &s; p โ”‚ โ”‚ stores address of s โ–ผ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ s โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ id โ”‚ 101 โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ marks โ”‚ 85 โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ p->marks โ”‚ โ””โ”€โ”€โ”€โ”€ accesses s.marks p->marks == (*p).marks 

14.20 . vs ->

Situation Operator Example
Structure object . s.marks
Pointer to structure -> p->marks
Pointer expanded form * and . (*p).marks
p->member means (*p).member. The parentheses are important in the expanded form.

14.21 Modifying a Structure Through a Pointer

struct Employee { int id; float salary; }; int main(void) { struct Employee e = {101, 45000.0f}; struct Employee *p = &e; p->salary = 50000.0f; printf("%.2f\n", e.salary); return 0; }

Since p points to e, modifying p->salary modifies e.salary.

14.22 Returning a Structure from a Function

A function can return a structure value.

#include <stdio.h>

struct Point {
    int x;
    int y;
};
struct Point createPoint(int x, int y) {
    struct Point p = {
        x, y
    };
    return p;
}
int main(void) {
    struct Point result;
    result = createPoint(10, 20);
    printf("(%d, %d)\n", result.x, result.y);
    return 0;
}

Returning the structure by value is valid.

Returning the local structureโ€™s value is valid because its value is copied to the caller. Returning its address is different: an automatic local object stops existing when the function returns.

14.23 Structure Size and sizeof

You can determine the size of a structure object using sizeof.

printf("%zu\n", sizeof(struct Student));

But do not assume that the structure size is always exactly the sum of the sizes of its members.

The implementation may insert padding bytes to satisfy alignment requirements.

 Possible memory layout โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ member A โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ padding โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ member B โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ padding โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ Padding depends on the implementation, member types and alignment requirements. 
Never write portable C code assuming that sizeof(struct S) must equal the simple sum of all member sizeof values.

14.24 Structure Alignment and Padding

Some types must start at suitable byte boundaries. The implementation may leave padding between members or after the last member. Use sizeof instead of adding member sizes yourself.

struct Example { char c; int x; };

It is possible for padding to appear between c and x.

The exact layout is implementation-dependent.

Why padding?

Padding helps place members and consecutive array elements at the alignments required by their types.

Why does it matter?

Structure size affects memory usage, arrays of structures and binary data layouts.

14.25 typedef with Structures โ€” Preview

C also allows a type alias to be created with typedef.

typedef struct { int id; float marks; } Student;

Then:

Student s1;

instead of:

struct Student s1;
Preview only: typedef has several important uses beyond structures and will be covered separately in the Enumerations & typedef topic.

14.26 Bit-Fields โ€” Advanced Preview

A bit-field requests a given number of bits for a member. For example, unsigned int enabled : 1 can store the values 0 and 1.

struct Flags { unsigned int ready : 1; unsigned int mode : 2; };

Bit-fields are useful in some low-level programming, embedded systems and hardware-oriented code.

The exact bit order and allocation layout can vary. Do not treat the declaration as a portable description of hardware registers or a file format.

14.27 What Is a Union?

A union is another user-defined type that contains multiple members.

The key difference is that the members share the same storage.

union Data { int number; float price; char letter; };

A union object has storage that is shared by its members.

Structure: members have separate storage.
Union: members overlap in shared storage.

14.28 Union Syntax

union UnionName { data_type member1; data_type member2; data_type member3; };

Example:

union Data { int number; float price; };

Create an object:

union Data data;

14.29 Union Memory Sharing

 union Data data โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ SHARED STORAGE โ”‚ โ”‚ โ”‚ โ”‚ number / price / letter โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ All members refer to overlapping storage. They do not each get an independent copy of the storage. 

For example:

union Data d; d.number = 100;

The union storage now contains the representation written through number.

If you then write:

d.price = 12.5f;

the shared storage changes again. The old integer and new floating-point value are not kept as independent values. In beginner code, read the member that was most recently written.

14.30 Initializing a Union

A union can be initialized when it is declared.

union Data { int number; float price; }; union Data d = {25};

Without a designated initializer, the first named member is initialized.

A designated initializer can explicitly select a member:

union Data d = { .price = 12.5f };
Designated initializers are available in C99 and later language standards.

14.31 Accessing Union Members

Union members are accessed with the same dot operator used for structure objects.

union Data d; d.number = 50; printf("%d\n", d.number);

The syntax is:

unionObject.member

The difference is not the member-access operator. The difference is how the members occupy storage.

14.32 Program Tracing: Union Storage

union Data { int number; float price; }; int main(void) { union Data d; d.number = 100; d.price = 12.5f; return 0; }
 Step 1 d.number = 100 โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ shared storage โ”‚ โ”‚ representation of 100 โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ Step 2 d.price = 12.5f โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ shared storage โ”‚ โ”‚ representation of 12.5f โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ The second write uses the same storage. The integer value 100 is not independently preserved as another member value. 
Writing one union member replaces the shared representation. The union does not remember which member you intended to use; keep a separate tag if the program needs that information.

14.33 Structure vs Union

Feature Structure Union
Member storage Separate storage for members Shared/overlapping storage
Values Members can hold independent values One shared representation is used at a time
Main purpose Represent a complete record Represent alternatives sharing storage
Member access . or -> . or ->
Memory usage Usually reflects storage for all members plus padding Based on shared storage and alignment requirements
 STRUCTURE โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ int id โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ float marks โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ char grade โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ Members occupy different regions. UNION โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ shared โ”‚ โ”‚ storage โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ Members overlap. 

14.34 When Should You Use a Structure?

Use a structure when multiple pieces of information need to exist together as one complete object.

Student

ID, name, marks, department

Employee

ID, name, salary, department

Product

Code, quantity, price

Point

X and Y coordinates

14.35 When Should You Use a Union?

Use a union when a value has several possible forms but the program needs one form at a time. If the ID, name, and marks must all exist together, use a structure instead.

Typical examples include:

  • Variant data representations
  • Memory-constrained systems
  • Low-level systems programming
  • Hardware-oriented representations
Keep a separate tag, such as an enum, to identify the stored alternative. Update the tag whenever you write a different union member, and check it before reading.

14.36 Tagged Union Concept

A common design pattern combines an enum-like tag with a union.

enum DataType { TYPE_INT, TYPE_FLOAT }; struct Value { enum DataType type; union { int number; float price; } data; };

The type member tells the program which union member should be interpreted as the current value.

 Value โ”‚ โ”œโ”€โ”€ type โ”‚ โ”œโ”€โ”€ TYPE_INT โ”‚ โ””โ”€โ”€ TYPE_FLOAT โ”‚ โ””โ”€โ”€ data โ”œโ”€โ”€ number โ””โ”€โ”€ price 

For example, a tag can say whether the union currently stores an integer or a float. The program checks the tag and uses the matching member; C does not enforce that match automatically.

14.37 Program Tracing: Pointer to Structure

struct Student { int id; int marks; }; int main(void) { struct Student s = {101, 85}; struct Student *p = &s; p->marks = 90; return 0; }
 Initial object s โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ id = 101 โ”‚ โ”‚ marks = 85 โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ After: p = &s p โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–บ s โ”‚ โ”œโ”€โ”€ id = 101 โ””โ”€โ”€ marks = 85 After: p->marks = 90 p โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–บ s โ”‚ โ”œโ”€โ”€ id = 101 โ””โ”€โ”€ marks = 90 

The pointer does not create another structure object. It points to the existing one.

14.38 Complete Program: Student Record

#include <stdio.h>

struct Student {
    int id;
    char name[50];
    float marks;
};
int main(void) {
    struct Student student;
    printf("Enter ID: ");
    scanf("%d", &student.id);
    printf("Enter name: ");
    scanf("%49s", student.name);
    printf("Enter marks: ");
    scanf("%f", &student.marks);
    printf("\nStudent Record\n");
    printf("ID = %d\n", student.id);
    printf("Name = %s\n", student.name);
    printf("Marks = %.2f\n", student.marks);
    return 0;
}

What happens?

  1. A structure type named Student is defined.
  2. A structure object named student is created.
  3. The ID is stored in student.id.
  4. The name is stored in student.name.
  5. The marks are stored in student.marks.
  6. Each member is accessed using the dot operator.

14.39 Complete Program: Structure + Function + Pointer

#include <stdio.h>

struct Student {
    int id;
    int marks;
};
void addBonus(struct Student *student) {
    student->marks += 5;
}
void display(struct Student student) {
    printf("ID = %d\n", student.id);
    printf("Marks = %d\n", student.marks);
}
int main(void) {
    struct Student s = {
        101, 85
    };
    addBonus(&s);
    display(s);
    return 0;
}

This small program combines three important concepts:

Structure

Groups ID and marks.

Pointer

Allows addBonus() to modify the original object.

Function

Separates modification and display logic.

14.40 Common Mistakes

Mistake 1 โ€” Forgetting struct

Student s;

This is not valid unless Student has been defined as a typedef name.

Normally write:

struct Student s;

Mistake 2 โ€” Using -> with an object

s->marks;

If s is a structure object, use:

s.marks;

Mistake 3 โ€” Using . with a structure pointer

p.marks;

If p is a pointer to structure, use:

p->marks;

Mistake 4 โ€” Comparing structures directly

if (s1 == s2)

Compare individual members instead.

Mistake 5 โ€” Assuming no padding

Do not assume that structure size equals the sum of all member sizes.

Mistake 6 โ€” Treating union members as independent

Union members share storage. Writing one member affects the shared representation.

14.41 Common Confusions

Confusion Correct Understanding
Structure and union are the same Both group members, but their storage models are different.
. and -> are interchangeable . is for an object; -> is for a pointer to structure/union.
Structure definition creates an object A definition describes the structure type; an object declaration creates an instance.
Structure size is member-size sum Padding and alignment can increase the size.
Union stores all values independently Its members overlap in shared storage.
Passing a structure automatically passes a reference C passes structure arguments by value. Use a pointer when modification of the original is required.

14.42 Structure Memory Model

 struct Employee e e โ”‚ โ–ผ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ id โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ name[] โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ salary โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ possible trailing padding โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ Each member has its own storage, although padding may also be present. 

For an array of structures, the complete structure object forms each array element.

struct Employee employees[3];

Conceptually:

employees[0] employees[1] employees[2]

Each array element includes space for the complete structure and any padding. Moving to the next element advances by sizeof the structure, not by a hand-calculated sum of its member sizes.

14.43 Flexible Array Members โ€” Variable-Length Records

A flexible array member has no fixed element count in the structure definition. It must come last, after at least one other named member. Allocate the fixed structure portion plus enough space for the required elements, and store the count separately.

Complete C program:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

struct Scores {
    size_t count;
    int marks[];
};

int main(void)
{
    size_t n = 3;
    if (n > (SIZE_MAX - sizeof(struct Scores)) / sizeof(int)) return 1;
    struct Scores *s = malloc(sizeof *s + n * sizeof s->marks[0]);
    if (s == NULL) return 1;
    s->count = n;
    for (size_t i = 0; i < n; ++i) s->marks[i] = (int)(i + 1) * 10;
    printf("Last mark = %d\n", s->marks[2]);
    free(s);
    return 0;
}

Expected output:

Last mark = 30

Step-by-step explanation:

  1. The struct declares a count followed by a flexible array.
  2. malloc reserves room for three ints after the fixed struct portion.
  3. The allocated object is freed after use.
Remember: sizeof the structure does not include the variable number of elements. Count their bytes separately and check the addition and multiplication for overflow when the count comes from input.

14.44 Compound Literals and Designated Initializers

A designated initializer names a member, so .y = 5 and .x = 2 do not depend on declaration order. A compound literal such as (struct Point){.x = 2, .y = 5} creates an object with those initialized values. Both forms have been standard since C99.

Complete C program:

#include <stdio.h>

struct Point { int x; int y; };

int main(void)
{
    struct Point p = (struct Point){.y = 5, .x = 2};
    printf("(%d, %d)\n", p.x, p.y);
    return 0;
}

Expected output:

(2, 5)

Step-by-step explanation:

  1. The named .y and .x fields are initialized regardless of order.
  2. p receives the resulting structure value.
  3. Members not explicitly initialized receive their typeโ€™s zero initialization, such as 0 for an int or a null pointer for a pointer member.
Remember: These forms make initialization clearer; they do not remove padding or make the structureโ€™s memory layout portable as a file format.

14.45 Quick Revision

๐Ÿ“Œ Structure โ†’ Groups different data types.

๐Ÿ“Œ Structure member access โ†’ .

๐Ÿ“Œ Structure pointer access โ†’ ->

๐Ÿ“Œ Array of structures โ†’ Stores multiple records.

๐Ÿ“Œ Nested structure โ†’ Structure inside another structure.

๐Ÿ“Œ Union โ†’ Members share the same memory.

๐Ÿ“Œ typedef โ†’ Creates a convenient type alias.

๐Ÿ“Œ Self-referential structure โ†’ Important for linked lists.
INTERACTIVE LEARNING

๐ŸŽฌ Structures & Unions โ€” Memory Relationship

Compare how structures keep members separately while unions share storage.

PROGRAM TRACING

๐Ÿ”Ž Program Tracing โ€” Structures & Unions

Trace structure initialization, a structure pointer, and member access through the arrow operator.

14.46 Quick MCQs

Select an answer first, then click Check Answer. A correct choice becomes green. If the answer is wrong, your choice becomes red and the correct option becomes green. The explanation appears below.

1. Which keyword is used to define a structure?
2. Which operator accesses a member through a structure variable?
3. Which operator is used with a pointer to a structure?
4. What is shared by members of a union?
5. Which keyword creates a type alias?
6. Which structure is important for linked lists?
PRACTICE

14.47 ๐ŸŽฏ Practice Problems

Practice structures, arrays of structures, nested structures, pointers, unions, typedef, and self-referential structures. Use ๐Ÿ’ป Solve It Yourself first, open Hint only when needed, and use Show Program after attempting the problem.

๐Ÿ“ˆ Structures & Unions Practice Progress
Solved 0 / 20
Completed with Solution 0
Total Score 0 / 400
Completion 0%
A problem counts as Solved when all test cases pass without opening the full solution. Problems completed after viewing the official solution are tracked separately.
1. Create a Student Structure

Problem 1: Create a Student structure containing roll number, name, and marks, initialize one student, and print the fields.

Input: No input.

Output: Print the initialized student data.

2. Read and Display One Student

Problem 2: Read one student's roll number, name, and marks and display the details.

Input: Roll number, one-word name, and marks.

Output: Print the same values.

3. Store Details of 5 Students

Problem 3: Store five students using an array of structures and print them.

Input: Five lines: roll number, one-word name, marks.

Output: Print five lines in the same order.

4. Student with Highest Marks

Problem 4: Read N students and print the student with the highest marks.

Input: N followed by N lines: roll, one-word name, marks.

Output: Print roll, name, and marks of the highest-scoring student.

5. Student with Lowest Marks

Problem 5: Read N students and print the student with the lowest marks.

Input: N followed by N lines: roll, one-word name, marks.

Output: Print roll, name, and marks of the lowest-scoring student.

6. Average Marks of Students

Problem 6: Read N students and calculate their average marks.

Input: N followed by N lines: roll, one-word name, marks.

Output: Print average marks to two decimal places.

7. Search Student by Roll Number

Problem 7: Read N students and search for a student using a roll number.

Input: N, N student records, then target roll number.

Output: Print name and marks if found, otherwise Not Found.

8. Sort Students by Marks

Problem 8: Sort student records in ascending order of marks.

Input: N followed by N lines: roll, one-word name, marks.

Output: Print sorted records, one per line.

9. Employee Annual Salary

Problem 9: Create an Employee structure, read monthly salary, and calculate annual salary.

Input: Employee id, one-word name, monthly salary.

Output: Print annual salary to two decimal places.

10. Pass a Structure to a Function

Problem 10: Pass a Student structure to a function and display its members.

Input: Roll number, one-word name, marks.

Output: Print the structure values from the function.

11. Return a Structure from a Function

Problem 11: Read two integers through a function that returns a structure containing both values and their sum.

Input: Two integers.

Output: Print the two values and their sum.

12. Access Members Using a Structure Pointer

Problem 12: Read a student record and display it through a structure pointer.

Input: Roll number and marks.

Output: Print both members using the arrow operator.

13. Nested Student and Date of Birth

Problem 13: Create a nested structure where Student contains a Date of Birth.

Input: Roll number followed by day, month, year.

Output: Print roll and date as DD-MM-YYYY.

14. Structure Containing an Array of 5 Marks

Problem 14: Create a Student structure containing an array of five marks and calculate their total.

Input: Five integer marks.

Output: Print the total.

15. Employee Structure Using typedef

Problem 15: Use typedef to create an Employee type, read id and salary, and print them.

Input: Employee id and salary.

Output: Print id and salary.

16. Union with int, float and char

Problem 16: Create a union containing int, float and char members. Assign and print each member one at a time.

Input: An integer, a float, and a character.

Output: Print the value immediately after assigning each corresponding union member.

17. Structure vs Union Memory with sizeof()

Problem 17: Create equivalent structure and union types and print whether the union size is less than or equal to the structure size.

Input: No input.

Output: Print "Union <= Structure".

18. Self-Referential Node Structure

Problem 18: Create two Node objects, link the first to the second, and print both values by following the link.

Input: Two integers.

Output: Print the two values.

19. Bank Account Final Balance

Problem 19: Create a BankAccount structure and calculate final balance after a deposit and withdrawal.

Input: Account number, initial balance, deposit, withdrawal.

Output: Print final balance to two decimal places.

20. Student Management: Add, Display and Search

Problem 20: Build a small student management program that reads N student records, displays all records, and searches for a target roll number.

Input: N, then N lines of roll/name/marks, then target roll.

Output: Print all records, then print Found: name marks or Not Found.

14.48 Key Takeaway

๐ŸŽฏ Remember:

Structure = Different data + Separate storage

Union = Different data + Shared storage

Structure variable โ†’ .

Structure pointer โ†’ ->

Self-referential structure โ†’ Foundation of Linked Lists
INTERVIEW PREPARATION

๐ŸŽค Structures & Unions โ€” Interview Questions

1. What is the main difference between a structure and a union?
2. What is the difference between . and ->?
3. Can one structure be assigned to another structure of the same type?
4. Can structures be compared directly using == in C?
5. What is a self-referential structure?
6. What is structure padding?
7. What is typedef used for with structures?
8. Why can union size differ from structure size?
PLACEMENT TIPS

๐Ÿ’ก Structures & Unions โ€” Placement Tips

  • For record-based problems, first identify the fields that belong together and define the structure clearly.
  • When sorting an array of structures, swap the entire structure object, not only one member.
  • Remember the member-access rule: object uses ., pointer uses ->.
  • Do not memorize exact structure sizes across systems; alignment and padding can change the result.
  • For unions, remember that members share storage, so treat them as alternative representations rather than independent simultaneous fields.
  • Self-referential structures connect this C topic directly to linked lists, trees, and other dynamic data structures.
EXTRA PRACTICE

โœ๏ธ Structures & Unions โ€” Extra Practice Questions

  1. Create a Product structure and find the product with the highest price.
  2. Store employee joining dates using a nested Date structure and sort by year.
  3. Create a structure for complex numbers and write functions for addition and subtraction.
  4. Use a union to store one of several simple sensor value types along with a separate type tag.
  5. Build a singly linked list node structure and manually connect three nodes.
  6. Investigate how changing member order affects sizeof for a structure on your compiler.
โ† Previous Topic: Pointers Next Topic: Preprocessor & Header Files โ†’