Tuesday, February 25, 2025

How to Use Derived Data Types in C Programming Language for Efficient Programming

In the C programming language, in addition to basic data types such as int, float, char, and double, there are derived data types that are based on basic types, but offer additional capabilities and flexibility when working with data. Derived data types are types that extend the functionality of primitive types by combining or referencing existing data. They allow the programmer to efficiently manage memory, group data, or define operations. Unlike primitive types, which directly store values, derived types often involve indirection, such as pointers, or the organization of multiple elements, such as arrays.

The main derived data types in the C language are:

Pointers: A data type that stores a memory address, e.g., int*, char* 
 
Arrays: A collection of elements of the same type, e.g., int arr [10]
 
Functions: The return value type of a function, e.g., int function ())

As you can see, in the C programming language, the main derived data types are pointers, arrays, and functions, and user-defined types such as struct, union, and enum are often implicitly included in this category, although they are formally different. We will write about user-defined types in the next blog post. Now we will concentrate only on derived data types that are not user-defined. If you are wondering how functions are a derived data type, then you simply need to know that functions in the C programming language have a type defined by their return value. They are not variables in the classical sense, but they are considered derived types because they allow defining operations on data. We hope this has cleared up any confusion. If anything is unclear, ask in the comments or contact us personally via the contact form on our blog.

A software engineer is considering using derived data types in the C programming language.

A software engineer is considering using derived data types in the C programming language

Pointers are one of the most powerful and characteristic aspects of the C language. They store the address in memory where the data is located, instead of the value itself. This allows for indirect access to data and dynamic memory allocation. Pointers in the C programming language are one of the key elements that make C so flexible and close to hardware. They are both fascinating and challenging, as they allow direct manipulation of memory, but their proper use can significantly improve program performance, while careless handling can lead to problems such as memory leaks and default errors. With pointers, you must code carefully and think carefully about when and how to use them.

Pointer Declaration:

int *ptr;

This means that ptr is a pointer to an integer value, int type specifies the type of data the pointer points to e.g., int, float, char, while * indicates that this is a pointer.

Key Operators:

& Address-of Operator - Retrieves the memory address of a variable.

* Dereference Operator - Accesses or modifies the value at the address stored in the pointer.

          Initialization Example:

int number = 10;

int *ptr = &number; // ptr points to the address of the number variable

Pointer Dereferencing:

    printf("Value at address: %d\n", *ptr); // Prints 10 

Dereferencing means accessing the value at the address that the pointer points to. Arrays in the C programming language are actually pointers to the first element. You can use them to traverse the array. Pointers can be used to pass arguments to functions to allow modifications of the original values. Function pointers allow functions to be called dynamically, based on their address. A pointer can also point to another pointer, allowing multiple levels of indirection. In any case, you will master pointers most easily through practice and coding.

Understanding and Applying Pointers in a Practical Example in C Programming Language

A pointer is a variable that stores the memory address of another variable rather than a value itself. In C, every variable resides at a specific location in memory, and pointers allow you to work with those locations directly. This makes them a cornerstone of low-level programming, enabling dynamic memory management, efficient data handling, and interaction with hardware. But why are pointers a big deal?

  • Direct Memory Access: Pointers let you manipulate memory explicitly, which is rare in high-level languages like Python or Java.
  • Efficiency: They allow passing large data structures to functions by reference rather than copying them.
  • Flexibility: Pointers enable dynamic memory allocation, e.g., using malloc and free and complex data structures like linked lists or trees.
  • Complexity and Risk: Misuse can lead to errors like segmentation faults, dangling pointers, or memory leaks, making them a serious matter that demands care.
Data types in C programming language

Data types in C programming language

Pointers in C are variables that hold memory addresses. Here's how they are declared and used:

Pointer Type: A pointer is declared by specifying the data type it points to. For example, int *p; declares a pointer p that points to a variable of type int.

The * Character: The asterisk * in front of the variable name indicates that it is a pointer.

Variable Address: To make a pointer point to a variable, you need to assign it the address of that variable using the & operator. For example, p = &x; assigns the pointer p the address of the variable x.

Syntax:

type* pointer_name;  // Declaration of a pointer

int x = 10;        // A regular integer variable

int* ptr = &x;     // Pointer ptr stores the address of x

Examples:

int *p; - Pointer to an integer.

char *s; - Pointer to a character.

float *f; - Pointer to a floating-point number.

Using Pointers, Dereferencing: 

To access the value pointed to by a pointer, the dereference operator * is used. For example, *p gives the value of the variable pointed to by p.

Pointers are an important part of the C programming language because they enable, dynamic memory allocation, passing arguments to functions by reference, working with arrays and structures and implementing complex data structures. Start your terminal and enter the following commands:

manuel@manuel-virtual-machine:~$ sudo apt-get update

manuel@manuel-virtual-machine:~$ sudo apt-get upgrade

manuel@manuel-virtual-machine:~$ clear

manuel@manuel-virtual-machine:~$ ls

manuel@manuel-virtual-machine:~$ cd tutorials

manuel@manuel-virtual-machine:/tutorials$ ls

manuel@manuel-virtual-machine:/tutorials$ cd c_tutorial

manuel@manuel-virtual-machine:/tutorials/c_tutorial$ ls

manuel@manuel-virtual-machine:/tutorials/c_tutorial$ mkdir student_grade_trucker

manuel@manuel-virtual-machine:/tutorials/c_tutorial$ cd student_grade_trucker

manuel@manuel-virtual-machine:/tutorials/c_tutorial/student_grade_trucker $ code .

Create a file and name it grades.c, then type the following code.

#include <stdio.h>

// Function to print a grade using a pointer

void print_grade(int* grade_ptr) {

    printf("Grade: %d\n", *grade_ptr); // Dereference to get the value 

}

// Function to print the memory address of a grade

void print_grade_address(int* grade_ptr) {

    printf("Address of grade: %p\n", (void*)grade_ptr); // Cast to void* for %p

}

// Function to swap two grades using pointers

void swap_grades(int* ptr1, int* ptr2) {

    int temp = *ptr1; // Store value at ptr1

    *ptr1 = *ptr2; // Replace ptr1's value with ptr2's value

    *ptr2 = temp; // Replace ptr2's value with temp

}

// Function to print all grades in array using a pointer

void print_all_grades(int* grades, int size) {

    printf("All grades: ");

    for (int i = 0; i < size; i++) {

        printf("%d ", *(grades + i)); // Pointer arithmetic to access each element

    }

    printf("\n");

}

int main() {

    // Array of student grades

    int grades[5] = {85, 92, 78, 95, 88};

    int size = 5;

    // Pointer to the array, points to the first element

    int* grades_ptr = grades;


    // Print initial grades using pointer to array

    printf("Initial Grades:\n");

    print_all_grades(grades_ptr, size);


    // Swap two grades using pointers

    printf("\nSwapping 1st and 4th grades:\n");

    swap_grades(&grades[0], &grades[3]); // Swap 85 and 95

    print_all_grades(grades_ptr, size);

 

    // Use pointer arithmetic to navigate and print grades

    printf("\nNavigating grades with pointer arithmetic:\n");

    int* moving_ptr = grades_ptr;

    for (int i = 0; i < size; i++) {

        printf("Grade at position %d: %d (Address: %p)\n", i + 1, *moving_ptr, (void*)moving_ptr);

        moving_ptr++; // Move to next grade, (increments by size of (int))

     }

     // Demonstrate NULL pointer

    int* null_ptr = NULL;

    printf("\nNULL pointer address: %p\n", (void*)null_ptr);

     return 0;

}

When you execute the given code, you will get the following result.

[Running] cd "d:\tutorials\c_tutorials\student_grade_trucker\" && gcc grades.c -o grades && "d:\tutorials\c_tutorials\student_grade_trucker\"grades

Initial Grades:

All grades: 85 92 78 95 88

 

Swapping 1st and 4th grades:

All grades: 95 92 78 85 88

 

Navigating grades with pointer arithmetic:

Grade at position 1: 95 (Address: 000000C8C8BFF700)

Grade at position 2: 92 (Address: 000000C8C8BFF704)

Grade at position 3: 78 (Address: 000000C8C8BFF708)

Grade at position 4: 85 (Address: 000000C8C8BFF70C)

Grade at position 5: 88 (Address: 000000C8C8BFF710)

 

NULL pointer address: 0000000000000000

 

[Done] exited with code=0 in 4.421 seconds

In general, try to understand the part of the code that deals with pointers on your own, while not ignoring the rest of the code, but understanding it as something you will learn. You can also see the same example in the following video.


C Tutorial - 4. Pointers in C, Student Grade Tracker example

Creating and Manipulating Arrays in C Programming

Arrays in C are a fundamental data structure used to store a collection of elements of the same data type in contiguous memory locations. They provide an efficient way to manage multiple values under a single variable name, accessible via indices. Unlike some higher-level languages, arrays in C are closely tied to the underlying memory model, giving programmers direct control but also requiring careful handling. An array is declared by specifying its data type, name, and size - number of elements it can hold. The size must be a constant expression known at compile time in standard C, pre-C99, though C99 introduced VLAs - Variable Length Arrays ().

Syntax:

type array_name[size];

Examples:

// Initialization at declaration

int numbers[5] = {10, 20, 30, 40, 50};
 
// Partial initialization (remaining elements set to 0)
int partial[5] = {1, 2};  // equivalent to {1, 2, 0, 0, 0}
 
// Without size (size inferred from initializer)
int inferred[] = {5, 10, 15, 20};

Types of Arrays in C: 

One-Dimensional Arrays - The simplest form, representing a linear collection of elements.

Example: int scores[10]; – an array of 10 integers.

Multi-Dimensional Arrays - Arrays of arrays, used for representing tables, matrices, or higher-dimensional data.

Two-Dimensional Example: int matrix[3][4]; – a 3x4 matrix.

Three-Dimensional Example: int cube[2][3][4]; – a 2x3x4 3D array.

Initialization:

int matrix[2][3] = {{1, 2, 3}, {4, 5, 6}};

VLAs - Variable Length Arrays:

Introduced in C99, VLAs allow the size to be determined at runtime using a variable.

Example:

int n = 5;

int vla[n];  // Size set at runtime

Note: VLAs are optional in C11 and later, and not all compilers support them fully.

Arrays in C programming language differ significantly from those in other languages due to C’s low-level nature. C++ inherits C’s array syntax and behavior, so basic arrays are identical in both languages. C++ offers std::vector, a dynamic array class for resizable arrays, while C relies on manual memory management with malloc/free for dynamic sizes. C++ arrays, raw C-style, lack bounds checking like C, but std::array introduced in C++11 provides a safer, fixed-size alternative with bounds checking via methods like .at().

In C programming languages, arrays are fixed-size unless using VLAs or dynamic allocation. Java arrays are fixed-size at creation, but cannot change size; for dynamic sizes, Java uses ArrayList. C has no bounds checking, risking undefined behavior, but Java throws an ArrayIndexOutOfBoundsException if you access beyond the array’s limits. C programming language requires manual allocation for dynamic arrays while Java handles memory automatically via garbage collection.

C programming language arrays require a fixed type while Python lists are dynamically typed and can hold mixed types. C arrays are fixed-size, except VLAs, while Python lists are dynamic and can grow or shrink. C uses raw memory access with indices or pointers. Python abstracts memory management and provides high-level operations. Unlike many languages, C lacks a native resizable array type, requiring manual memory management for dynamic needs. The tight coupling with pointers gives C arrays unmatched efficiency but increases the risk of errors like buffer overflows.

For arrays, we code a comprehensive example of using one-dimensional and two-dimensional arrays to manage student grades. Start your terminal and enter the following commands:

manuel@manuel-virtual-machine:~$ sudo apt-get update

manuel@manuel-virtual-machine:~$ sudo apt-get upgrade

manuel@manuel-virtual-machine:~$ clear

manuel@manuel-virtual-machine:~$ ls

manuel@manuel-virtual-machine:~$ cd tutorials

manuel@manuel-virtual-machine:/tutorials$ ls

manuel@manuel-virtual-machine:/tutorials$ cd c_tutorial

manuel@manuel-virtual-machine:/tutorials/c_tutorial$ ls

manuel@manuel-virtual-machine:/tutorials/c_tutorial$ mkdir student_grade_trucker

manuel@manuel-virtual-machine:/tutorials/c_tutorial$ cd student_grade_manager

manuel@manuel-virtual-machine:/tutorials/c_tutorial/student_grade_manager $ code .

Create a file and name it manager.c, then type the following code.

#include <stdio.h>

int main() {

    // One-dimensional array for grades of one student

    int student_grades[5] = {85, 90, 78, 92, 88};

    int num_grades = 5;

    // Print all grades using array indexing

    printf("Student Grades:\n");

    for (int i = 0; i < num_grades; i++) {

        printf("Grade %d: %d\n", i + 1, student_grades[i]);

    }

    // Two-dimensional array for grades of multiple students

    int class_grades[3][4] = {

        {85, 90, 78, 92}, // Student 1

        {88, 95, 82, 87}, // Student 2

        {76, 80, 85, 91}  // Student 3

    };

    int num_students = 3;

    int num_subjects = 4;

    // Print class grades using nested loops

    printf("\nClass Grades:\n");

    for (int i = 0; i < num_students; i++) {

        printf("Student %d: ", i + 1);

        for (int j = 0; j < num_subjects; j++) {

            printf("%d ", class_grades[i][j]);

        }    

        printf("\n");

    }

    // Accessing a specific grade with pointers

    int* grade_ptr = &class_grades[1][2]; // Pointer to Student2, Subject 3 - 82

    printf("\nStudent 2, Subject 3: %d (Address: %p)\n", *grade_ptr, (void*)grade_ptr); 

    // VLA - Variable Length Array, example C99

    int num_exams = 3;

    int vla_grades[num_exams];

    vla_grades[0] = 95;

    vla_grades[1] = 88;

    vla_grades[2] = 91;

    printf("\nVLA Grades:\n");

    for (int i = 0; i < num_exams; i++) {

        printf("Exam %d: %d\n", i + 1, vla_grades[i]);

     }

     return 0;

 }

When you execute the given code, you will get the following result.

[Running] cd "d:\tutorials\c_tutorials\student_grade_manager\" && gcc manager.c -o manager && "d:\tutorials\c_tutorials\student_grade_manager\"manager

Student Grades:

Grade 1: 85

Grade 2: 90

Grade 3: 78

Grade 4: 92

Grade 5: 88

 

Class Grades:

Student 1: 85 90 78 92

Student 2: 88 95 82 87

Student 3: 76 80 85 91

 

Student 2, Subject 3: 82 (Address: 0000006E50DFF6A8)

 

VLA Grades:

Exam 1: 95

Exam 2: 88

Exam 3: 91

 

[Done] exited with code=0 in 1.591 seconds

You can also see the same example in the following video.


C Tutorial - 5. Arrays in C, Student Grade Manager example

Efficient Use of Functions in C Programming

Functions are the fundamental building blocks in C, allowing programmers to break down a program into reusable, modular pieces of code. A function is a named block of code that performs a specific task and can be called from other parts of the program. Functions improve readability, maintainability, and reusability, making them essential for structured programming. In the C programming language, a function consists of:

  • Return type - Specifies the type of value the function returns, e.g., int, float, void for no return.
  • Function name - A unique identifier for calling the function.
  • Parameters, optional - Variables passed to the function on which it operates.
  • Body - A block of code enclosed in {} that defines what the function does.
Key characteristics of functions in the C programming language are:
  • Declaration - Specifies the function name, return type, and parameters without the body, often placed in headers or before main to inform the compiler.
  • Definition - Includes the body and implements the function's logic.
  • Scope - Parameters and variables declared within a function are local to that function and inaccessible outside of it.
  • Global variables - Declared outside of functions are accessible to all functions unless shadowed by local variables.
  • Return statement - A function can return a single value using return. For void functions, return; terminates the function early without returning a value.
  • Function prototypes - If a function is defined after its call, a prototype, a declaration before the call, is needed to avoid compilation errors.
  • Pass by value - By default, C passes arguments to functions by value, meaning copies of the arguments are made. Changes to parameters within the function do not affect the original variables unless pointers are used.

Functions in the C programming language have certain characteristics and limitations that distinguish them from C++ and other languages. In the C programming language, passing is by value only. To modify the original variable, you must use pointers. In the C programming language, there is no overloading, rather each function must have a unique name. You cannot have two functions with the same name. In the C programming language, all parameters must be explicitly passed, there are no default values. In the C programming language, functions are standalone, and cannot be part of objects or classes because the C programming language is not object-oriented.

Furthermore, functions in the C programming language are global or static, without namespaces, and can use pointers for dynamic memory allocation, which requires manual deallocation. A function in the C programming language can only return one value. For multiple values, you must use pointers or structures. The C programming language has no built-in exception handling, errors are handled manually with return codes. Without overloading or default arguments, the C programming language requires explicitness, which can increase code length. These are basically coding limitations in the C programming language, but working with functions in practice is simple. We will code an example that demonstrates various aspects of functions in C, focusing on a library management system. Start your terminal and enter the following commands:

manuel@manuel-virtual-machine:~$ sudo apt-get update

manuel@manuel-virtual-machine:~$ sudo apt-get upgrade

manuel@manuel-virtual-machine:~$ clear

manuel@manuel-virtual-machine:~$ ls

manuel@manuel-virtual-machine:~$ cd tutorials

manuel@manuel-virtual-machine:/tutorials$ ls

manuel@manuel-virtual-machine:/tutorials$ cd c_tutorial

manuel@manuel-virtual-machine:/tutorials/c_tutorial$ ls

manuel@manuel-virtual-machine:/tutorials/c_tutorial$ mkdir student_grade_trucker

manuel@manuel-virtual-machine:/tutorials/c_tutorial$ cd library_management_system

manuel@manuel-virtual-machine:/tutorials/c_tutorial/ library_management_system$ code .

Create a file and name it library.c, then type the following code.

#include <stdio.h>

#include <string.h>

// Function prototypes

void display_menu();

void add_book_message(char* title, char books[][50], int* size);

void list_books(char books[][50], int size);

void exit_message();


// Main function

int main() {

    char library[4][50] = {

        "The C Programming Language\n",

        "Clean Code\n",

        "Introduction to Algorithms\n"

    };

    int num_books = 3;

    display_menu();

    printf("Adding a new book:\n");


    add_book_message("Design Patterns\n", library, &num_books);

    printf("Listing all books:\n");


    list_books(library, num_books);

    exit_message();

    return 0;

}

// Fuction definitions

void display_menu() {

    printf("=== Library Management System ===\n");

    printf("1. Add Book\n");

    printf("2. List Books\n");

    printf("3. Exit\n");

    printf("=================================\n");

}

void add_book_message(char* title, char books[][50], int* size) {

    printf("Book added: %s", title);

    // Add the new book to the array at the next available position

    strcpy(books[*size], title); // Copy the title into the array

    (*size)++;

}

void list_books(char books[][50], int size) {

    printf("Books in the library:\n");

    for (int i = 0; i < size; i++) {

        printf("- %s", books[i]);

    }

}

void exit_message() {

    printf("Exiting the Library Management System. Goodbye!\n"); 

}


When you execute the given code, you will get the following result:

[Running] cd "d:\tutorials\c_tutorials\library_management_system\" && gcc library.c -o library && "d:\tutorials\c_tutorials\library_management_system\"library

=== Library Management System ===

1. Add Book

2. List Books

3. Exit

=================================

Adding a new book:

Book added: Design Patterns

Listing all books:

Books in the library:

- The C Programming Language

- Clean Code

- Introduction to Algorithms

- Design Patterns

Exiting the Library Management System. Goodbye!

 

[Done] exited with code=0 in 1.503 seconds

You can also see the same example in the following video.



C Tutorial - 6. Functions in C, Library Management System example

A comprehensive example combining pointers with arrays, functions, and dynamic memory to simulate a simple student trucker system. This program uses arrays to store student names, pointers to access and manipulate data, and functions that print messages. Start your terminal and enter the following commands:

manuel@manuel-virtual-machine:~$ sudo apt-get update

manuel@manuel-virtual-machine:~$ sudo apt-get upgrade

manuel@manuel-virtual-machine:~$ clear

manuel@manuel-virtual-machine:~$ ls

manuel@manuel-virtual-machine:~$ cd tutorials

manuel@manuel-virtual-machine:/tutorials$ ls

manuel@manuel-virtual-machine:/tutorials$ cd c_tutorial

manuel@manuel-virtual-machine:/tutorials/c_tutorial$ ls

manuel@manuel-virtual-machine:/tutorials/c_tutorial$ mkdir student_grade_trucker

manuel@manuel-virtual-machine:/tutorials/c_tutorial$ cd student_trucker_system

manuel@manuel-virtual-machine:/tutorials/c_tutorial/student_trucker_system$ code .

Create a file and name it tracker.c, then type the following code.

#include <stdio.h>

// Function to print a welcome message

void print_welcome_message() {

    printf("Welcome to the Student Tracker System!\n");

}

// Function to print a goodbye message

void print_goodbye_message() {

    printf("Thank you for using the Student Tracker System. Goodbye!\n");

}

// Function to print a message about a specific student using a pointer

void print_student_info(char* student_ptr) {

    printf("Current student: %s", student_ptr); // %s includes new line from string

}

// Function to print message indicating the student list is being displayd

void print_list_message() {

    printf("Here is the list of students:\n");

}

int main() {

    // Array of student names, a simple array of character arrays

    char students[5][20] = {

        "Alice Smith\n",

        "Bob Johnson\n",

        "Charlie Brown\n",

        "Diana White\n",

        "Eve Davis\n"

    };

    // Pointer to the array of students

    char (*array_ptr)[20] = students; // Pointer of an array of 20 chars

    // Call function to print welcome message

    print_welcome_message();

    // Print a message before showing the student list

    print_list_message;

    // Use a pointer to iterate through the array and print student info

    char* student_ptr; // Pointer to a single student name

    for (int i = 0; i < 5; i++) {

        student_ptr = array_ptr[i]; // Point to the current student name

        printf("Student %d - ", i + 1); // Print student number, simple output

        print_student_info(student_ptr); // Call function to print student name

    }

 

    // Demonstrate pointer manipulation, point to the specific student

    student_ptr = array_ptr[2]; // Point to the third student, Charlie Brown

    printf("\nSelected student using pointer:\n");

    print_student_info(student_ptr);

    // Use pointer to move to another student manually

    student_ptr = array_ptr[0]; // Point to the first student, Alice Smith

    printf("\nMoved pointer to the first student:\n");

    print_student_info(student_ptr);

    // Show how to use pointer to access the last sudent

    student_ptr = array_ptr[4]; // Point to the fifth student, Eve Davis

    printf("\nMoved pointer to the last student\n");

    print_student_info(student_ptr);

    // Call function to print goodbye message

    print_goodbye_message();

    return 0;

}

When you execute the given code, you will get the following result:

[Running] cd "d:\tutorials\c_tutorials\student_trucker_system\" && gcc tracker.c -o tracker && "d:\tutorials\c_tutorials\student_trucker_system\"tracker

Welcome to the Student Tracker System!

Student 1 - Current student: Alice Smith

Student 2 - Current student: Bob Johnson

Student 3 - Current student: Charlie Brown

Student 4 - Current student: Diana White

Student 5 - Current student: Eve Davis

 

Selected student using pointer:

Current student: Charlie Brown

 

Moved pointer to the first student:

Current student: Alice Smith

 

Moved pointer to the last student

Current student: Eve Davis

Thank you for using the Student Tracker System. Goodbye!

 

[Done] exited with code=0 in 4.529 seconds

You can also see the same example in the following video:



C Tutorial - 7. Derived data types in C, Student Tracker System example


 

 

 

 

 

 

 

No comments:

Post a Comment