Back to C Programming
2026-03-299 min read

structures or unions with array members

Learn structures or unions with array members step by step with clear examples and exercises.

Why This Matters

In this lesson, we will delve deeper into C programming by exploring structures and unions with array members. Understanding these concepts is essential for mastering complex data structures, tackling real-world problems, preparing for interviews, and excelling in competitive coding.

Prerequisites

To fully grasp the topics discussed in this lesson, you should have a solid foundation in:

  1. Basic C syntax (variables, operators, control statements)
  2. Data types (int, float, char)
  3. Pointers in C
  4. Structures and unions (basic usage)
  5. Dynamic memory allocation (malloc, calloc, realloc, free)
  6. File I/O (fopen, fread, fwrite, fprintf, fscanf)
  7. Basic understanding of arrays and pointers

Core Concept

Structures and unions allow us to create custom data types that can group multiple variables of different data types together. In this lesson, we will focus on structures with array members and unions containing arrays, as well as exploring some common use cases and best practices.

Structures with Array Members

A structure can contain an array as one of its members. This enables us to store related data within a single structure instance. Here's an example:

struct Student {
char name[50];
int age;
float gpa;
int scores[3]; // An array of 3 integers to store test scores
};

In the above code, we have defined a structure called Student, which contains four members: name, age, gpa, and an array scores. Each instance of this structure will have space for three test scores.

To access the elements of an array within a structure, you can use the dot operator (.). For example:

struct Student s;
s.scores[0] = 90; // Setting the first score
printf("%d\n", s.scores[0]); // Printing the first score

Array Sizes and Dynamic Memory Allocation

When defining a structure with an array member, it's essential to carefully consider the size of the array based on your specific use case. If you need a variable-sized array, you can use dynamic memory allocation functions like malloc() or calloc() to allocate memory for the array at runtime.

Initializing Structures with Array Members

To initialize a structure with an array member, you can either provide values for each element individually or use an initializer list. Here's an example of both methods:

struct Student s = { .name = "John", .age = 20, .gpa = 3.5, .scores = {90, 85, 92} }; // Initializing with individual values and array initialization

struct Student s2 = {"Jane", 19, 3.7, {88, 94, 96}}; // Initializing with an initializer list

Unions with Array Members

Unions are similar to structures but allow multiple data types to occupy the same memory location. Here's an example of a union containing an array:

union Data {
int i;
float f;
char str[10];
};

union Data arr[5]; // An array of 5 unions, each capable of storing an integer, float, or string

In this example, we have defined a union called Data, which can store either an integer, a floating-point number, or a character array. We then create an array of five such unions. Each element in the array can switch between these three data types.

To switch between data types within a union, you can use the union keyword followed by the name of the union and the desired data type. For example:

union Data arr[5];
arr[0].i = 42; // Setting the first union to store an integer (42)
printf("%d\n", arr[0].i); // Printing the integer stored in the first union
arr[0].f = 3.14; // Switching the first union to store a floating-point number (3.14)
printf("%f\n", arr[0].f); // Printing the floating-point number stored in the first union

Array Sizes and Dynamic Memory Allocation for Unions

When defining a union with an array member, it's essential to consider the size of the array based on your specific use case. If you need a variable-sized array, you can use dynamic memory allocation functions like malloc() or calloc() to allocate memory for the array at runtime.

Initializing Unions with Array Members

To initialize a union with an array member, you can either provide values for each element individually or use an initializer list. Here's an example of both methods:

union Data arr[5] = { [0] = { .i = 42 }, [1] = { .f = 3.14 }, [2] = { .str = "Hello" } }; // Initializing with individual values and array initialization

union Data arr2[5] = { [0] = { .str = "World" }, [1] = { .i = 7 }, [2] = { .f = 2.718 } }; // Initializing with an initializer list

Worked Example

Let's create a simple program that uses structures with array members to represent a group of students and their test scores, as well as read and write data from/to a file:

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

struct Student {
char name[50];
int age;
float gpa;
int scores[3];
};

void readStudents(const char *filename, struct Student students[], int size) {
FILE *file = fopen(filename, "r");
if (file == NULL) {
printf("Error: Could not open file %s\n", filename);
return;
}

for (int i = 0; i < size && fscanf(file, "%s%d%f%d%d%d", students[i].name, &students[i].age, &students[i].gpa, &students[i].scores[0], &students[i].scores[1], &students[i].scores[2]) == 6; ++i) {}
fclose(file);
}

void writeStudents(const char *filename, const struct Student students[], int size) {
FILE *file = fopen(filename, "w");
if (file == NULL) {
printf("Error: Could not open file %s for writing\n", filename);
return;
}

for (int i = 0; i < size; ++i) {
fprintf(file, "%s %d %.2f %d %d %d\n", students[i].name, students[i].age, students[i].gpa, students[i].scores[0], students[i].scores[1], students[i].scores[2]);
}
fclose(file);
}

int main() {
const int STUDENT_COUNT = 3;
struct Student students[STUDENT_COUNT];

// Reading student data from a file
readStudents("students.txt", students, STUDENT_COUNT);

// Printing student data
for (int i = 0; i < STUDENT_COUNT; ++i) {
printf("\nStudent %d:\n", i + 1);
printf("Name: %s\n", students[i].name);
printf("Age: %d\n", students[i].age);
printf("GPA: %.2f\n", students[i].gpa);
printf("Test Scores:\n");
for (int j = 0; j < 3; ++j) {
printf("%d ", students[i].scores[j]);
}
}

// Writing student data to a file
writeStudents("students_backup.txt", students, STUDENT_COUNT);

return 0;
}

In this example, we have defined a structure called Student, which contains four members: name, age, gpa, and an array scores. We then read student data from a file named students.txt using the readStudents() function and print out the stored data for each student. After that, we write the student data to a backup file named students_backup.txt using the writeStudents() function.

Common Mistakes

  1. Forgetting to initialize structure members: Make sure you initialize all structure members when declaring a new instance of the structure.
  2. Accessing array elements outside the bounds: Ensure that you never access an element of an array within a structure using an index greater than or equal to the size of the array.
  3. Mixing up structures and unions: Be careful not to use the union keyword where you intended to use the struct keyword, and vice versa.
  4. Forgetting to include necessary headers (e.g., `` for string functions): Always include the appropriate header files when using functions that are not part of the standard C library.
  5. Not freeing dynamically allocated memory: If you allocate memory dynamically using functions like malloc(), remember to deallocate it using free() when you're done with it to avoid memory leaks.
  6. Not handling errors properly: Always check for errors, such as file I/O errors or out-of-bounds array accesses, and handle them appropriately.
  7. Forgetting to close files: When reading from or writing to a file, always remember to close the file when you're done with it using fclose().
  8. Not considering edge cases: Be mindful of edge cases, such as empty arrays or structures, and handle them accordingly.
  9. Misusing dynamic memory allocation: Be careful when using dynamic memory allocation functions like malloc(), calloc(), realloc(), and free() to ensure that you allocate the correct amount of memory and deallocate it properly.
  10. Not validating user input: Always validate user input, such as ensuring that array indices are within bounds and that strings do not exceed their allocated size.

Subheadings under Common Mistakes

  • Handling Errors Properly
  • Closing Files Correctly
  • Considering Edge Cases
  • Managing Dynamic Memory Allocation Effectively
  • Validating User Input

Practice Questions

  1. Modify the example program to calculate and print the average test score for each student.
  2. Create a union called ComplexNumber that can represent a complex number as either an array of two floating-point numbers (real and imaginary parts) or a single structure containing real and imaginary parts as separate variables. Write a function that takes a pointer to a ComplexNumber union and performs addition on the complex numbers represented by the union.
  3. Create a structure called Employee that contains members for name, age, department, designation, and an array of three integers representing the employee's salary components (basic, HRA, and DA). Write a function that calculates and prints the total salary of an employee given a pointer to an instance of the Employee structure.
  4. Modify the example program to read student data from standard input instead of a file.
  5. Create a structure called Point that represents a point in a 2D plane with x and y coordinates as separate members. Write a function that calculates the distance between two points given pointers to instances of the Point structure.
  6. Create a union called Date that can represent a date as either an array of three integers (day, month, year) or a single structure containing day, month, and year as separate variables. Write a function that takes a pointer to a Date union and calculates the number of days between two dates.
  7. Modify the example program to sort the students based on their test scores in descending order.
  8. Create a structure called Book that represents a book with members for title, author, publication year, and an array of integers representing the page numbers of important sections. Write a function that calculates the total number of pages in a book given a pointer to an instance of the Book structure.
  9. Create a union called Time that can represent a time as either an array of three integers (hours, minutes, seconds) or a single structure containing hours, minutes, and seconds as separate variables. Write a function that takes a pointer to a Time union and calculates the total number of seconds since midnight.
  10. Modify the example program to read student data from multiple files and merge them into a single list.

FAQ

  1. Can I have an array as a member of a union? No, unions cannot contain arrays because they share the same memory location for their members.
  2. Is it possible to initialize all elements of an array within a structure at once? Yes, you can use an initializer list to initialize all elements of an array within a