Custom Types
1 The Need for Custom Data Types
In programming, predefined data types like integers, floating-point numbers, and characters are often insufficient for solving real-world problems. To manage more complex data, we need to create custom types. Examples include:
-
Representing a student’s information with fields such as name, age, and grades.
-
Modeling a point in 2D space with x and y coordinates.
-
Grouping related constants, such as days of the week or months of the year.
Custom data types allow for better organization, readability, and reusability of code.
2 Structures and Their Usage
A structure is a custom data type that groups related variables of different types under one name. Each variable inside a structure is called a member or field.
Vars Student: structure {name: string, age: integer, grade: float} s: Student Start read (s.name) read (s.age) read (s.grade) write ("Name:", s.name) write ("Age:", s.age) write ("Grade:", s.grade) End
3 Enumerations
An enumeration is a custom data type used to define a set of named integer constants. Enumerations are useful for representing states or categories.
Vars Day: enum {Monday, Tuesday, Wednesday, Thursday, Friday} today: Day Start today ← Wednesday write ("Today is", today) End
4 Applications in C (Struct, Enum, Union, Typedef)
C provides several ways to create and use custom data types.
4.1 Structures in C
Structures in C are defined using the struct keyword. Here’s an example:
#include <stdio.h>
struct Student {
char name[50];
int age;
float grade;
};
int main() {
struct Student s = {"Alice", 20, 85.5};
printf("Name: %s\n", s.name);
printf("Age: %d\n", s.age);
printf("Grade: %.2f\n", s.grade);
return 0;
}
A struct (short for structure) in C is a user-defined data type that allows grouping variables of different types under a single name. It is useful for organizing related data and creating more readable and maintainable code.
4.1.1 Syntax
The general syntax for defining a struct is as follows:
struct StructName {
dataType member1;
dataType member2;
// Add more members as needed
};
Here:
-
StructNameis the name of the structure. -
member1, member2, ...are the data members (variables) inside the structure.
4.1.2 Example: Defining and Using a struct
#include <stdio.h>
// Define a struct to represent a point in 2D space
struct Point {
int x; // x-coordinate
int y; // y-coordinate
};
int main() {
// Declare and initialize a variable of type struct Point
struct Point p1 = {10, 20};
// Access and modify members of the struct
printf("Point: (%d, %d)\n", p1.x, p1.y);
p1.x = 15; // Update the x-coordinate
printf("Updated Point: (%d, %d)\n", p1.x, p1.y);
return 0;
}
Output:
Point: (10, 20)
Updated Point: (15, 20)
4.1.3 Example: Representing a Student Record
A common use of struct is to represent complex entities like student records.
#include <stdio.h>
#include <string.h>
// Define a struct to represent a student
struct Student {
char name[50];
int age;
float gpa;
};
int main() {
// Declare and initialize a student
struct Student s1;
strcpy(s1.name, "Alice");
s1.age = 20;
s1.gpa = 3.8;
// Print student details
printf("Student Name: %s\n", s1.name);
printf("Age: %d\n", s1.age);
printf("GPA: %.2f\n", s1.gpa);
return 0;
}
Output:
Student Name: Alice
Age: 20
GPA: 3.80
4.1.4 Example: Nested struct
#include <stdio.h>
// Define a struct to represent a date
struct Date {
int day;
int month;
int year;
};
// Define a struct to represent an event
struct Event {
char name[50];
struct Date date; // Nested struct
};
int main() {
// Declare and initialize an event
struct Event event;
strcpy(event.name, "Conference");
event.date.day = 15;
event.date.month = 8;
event.date.year = 2024;
// Print event details
printf("Event: %s\n", event.name);
printf("Date: %02d/%02d/%d\n", event.date.day, event.date.month, event.date.year);
return 0;
}
Output:
Event: Conference
Date: 15/08/2024
4.1.5 Example: Array of struct
You can use arrays to manage multiple instances of a struct.
#include <stdio.h>
// Define a struct to represent a book
struct Book {
char title[100];
char author[50];
int year;
};
int main() {
// Declare an array of books
struct Book library[2] = {
{"The C Programming Language", "Brian Kernighan", 1988},
{"Clean Code", "Robert C. Martin", 2008}
};
// Print details of all books
for (int i = 0; i < 2; i++) {
printf("Book %d: %s by %s (%d)\n", i + 1, library[i].title, library[i].author, library[i].year);
}
return 0;
}
Output:
Book 1: The C Programming Language by Brian Kernighan (1988)
Book 2: Clean Code by Robert C. Martin (2008)
4.1.6 Using and Not Using typedef with struct
When you define a structure with the struct keyword, you need to explicitly use the struct keyword every time you declare a variable of that structure type.
#include <stdio.h>
struct Person { // Defining the structure type
char name[50];
int age;
};
int main() {
struct Person person1; // Declaring a variable of the structure type
// Assigning values
person1.age = 30;
snprintf(person1.name, sizeof(person1.name), "John");
printf("Name: %s\n", person1.name);
printf("Age: %d\n", person1.age);
return 0;
}
The typedef keyword allows you to create an alias for the structure type, making it easier to declare variables without using the struct keyword repeatedly.
#include <stdio.h>
typedef struct { // Defining the structure type and creating an alias
char name[50];
int age;
} Person; // \texttt{Person} is now the alias for the structure type
int main() {
Person person1; // Declaring a variable using the alias
// Assigning values
person1.age = 30;
snprintf(person1.name, sizeof(person1.name), "John");
printf("Name: %s\n", person1.name);
printf("Age: %d\n", person1.age);
return 0;
}
Key Differences
-
With
struct: You must use thestructkeyword when declaring a variable of that type.-
Example:
struct Person person1;
-
-
With
typedef struct: You can declare the structure type without thestructkeyword by creating an alias.-
Example:
Person person1;(HerePersonis the alias created usingtypedef).
-
Which One to Use?
-
typedef structis more commonly used because it simplifies the code by eliminating the need to typestructeach time you declare a variable of that structure type. -
structalone is useful when you want to keep the distinction between the structure type and the alias, or if you don’t want to create a typedef.
In modern C programming, typedef struct is preferred for readability and convenience, especially when defining many structures. However, you can use either based on your preference.
4.2 Unions in C
A union allows different fields to share the same memory location. It is used when only one of the fields is active at a time.
#include <stdio.h>
union Data {
int i;
float f;
char str[20];
};
int main() {
union Data d;
d.i = 42;
printf("Integer: %d\n", d.i);
d.f = 3.14;
printf("Float: %.2f\n", d.f);
return 0;
}
A union in C is a user-defined data type that allows multiple members to share the same memory location. While similar to struct, where members have individual memory locations, in a union, the size is determined by its largest member. This makes unions memory-efficient when only one member is used at a time.
Key Points:
-
All members share the same memory.
-
Only one member can hold a value at any given time.
-
Useful for applications like data conversion or working with hardware registers.
Syntax of Union in C
union UnionName {
member_type1 member_name1;
member_type2 member_name2;
...
};
Example:
union Data {
int i;
float f;
char str[20];
};
Here, Data is a union with three members: an integer, a floating-point number, and a string. All members share the same memory.
Another Example of Using a Union
#include <stdio.h>
union Data {
int i;
float f;
char str[20];
};
int main() {
union Data d;
d.i = 10;
printf("Integer: %d\n", d.i);
d.f = 3.14;
printf("Float: %.2f\n", d.f);
snprintf(d.str, sizeof(d.str), "Hello");
printf("String: %s\n", d.str);
return 0;
}
Output:
Integer: 10
Float: 3.14
String: Hello
Explanation:
-
Assigning a value to
d.istores it in the memory. -
Reassigning a value to
d.foverwrites the same memory. -
Writing to
d.strsimilarly overwrites the memory.
4.2.1 Common Use Cases for Unions
-
Memory Optimization: Save space in scenarios where only one variable is used at a time.
-
Data Conversion: For example, treating the same memory as both an integer and a byte array for bit manipulation.
-
Hardware Access: Direct access to hardware registers where different fields represent different configurations.
4.2.2 Limitations of Unions
-
Only one member can hold a meaningful value at a time.
-
Care must be taken to track which member is active to avoid undefined behavior.
4.3 Enumerations in C
Enumerations are defined using the enum keyword. Example:
#include <stdio.h>
enum Day {Monday, Tuesday, Wednesday, Thursday, Friday};
int main() {
enum Day today = Wednesday;
printf("Today is %d\n", today); // Prints the integer value of Wednesday
return 0;
}