Week 10: Structure, Unions, Bit Manipulation and Enumerations

A structure is a composite data type that allows you to group together variables of different data types under a single name. This grouping enables you to organize related data elements efficiently.

Structure Definitions, Initialization, and Accesing Structure Members

// Defining a structure to represent a point in 2D space
struct Point {
    int x;
    int y;
};

The identifier Point is the structure tag, which you use with struct to declare variables of the structure type. Variables declared within a struct’s braces are the structure’s members. A struct’s members must have unique names, though separate structure types may contain members of the same name without conflict. Each structure definition ends with a semicolon.

Self-Referential Structures

A self-referential structure, also known as a recursive structure, is a structure type in C that contains a member that is a pointer to the same type of structure. This concept is commonly used in data structures like linked lists, trees, and graphs, where each element points to another element of the same type, creating a chain or hierarchy.

struct Point {
    int x;
    int y;
    struct Point *next; // Pointer to the next Point structure
};

Defining Variables of Structure Types

Defining variables of structure types in C involves declaring instances of the structure by specifying the structure's name, followed by the variable name. Here's how you can define variables of structure types:

We can also define variables of a given structure type directly after the structure definition, all within the same line, separating the structure definition from the variable declaration by a semicolon.

Example

Accessing Structure Members

From the above example, you see that we can access structure members using the dot (.) operator when dealing with structure variables directly, and you can use the arrow (->) operator when dealing with pointers to structure variables.

Here's how you can use both operators:

  1. Dot Operator (.):

    • It is used to access members of a structure when you have a direct instance of that structure.

  2. Arrow Operator (->):

    • The arrow operator (->) is used to access members of a structure when you have a pointer to that structure.

    • The expression ptr->x is equivalent to (*ptr).x which dereferences the pointer and accesses the member x using the structure member operator (.). The parentheses are needed here because the structure member operator (.) has higher precedence than the pointer dereferencing operator (*). The structure pointer operator and structure member operator have the highest precedence and group from left-to-right, along with parentheses (for calling functions) and brackets ([]) used for array indexing.

It is important to note that you do not put spaces around the -> and . operators to emphasize that the expressions the operators are contained in are essentially single variable names.

Array of Structure Objects

You can create arrays of structure objects to store multiple instances of a structure. This is useful when dealing with collections of related data. Each element of the array is a structure object, and you can access its members using the dot operator (.) or arrow operator (->) if dealing with pointers.

Using Structure with Functions

With structures, you can pass to functions: individual structure members, entire structure objects, or pointers to structure objects. Structures can be passed to functions either by value or by reference:

  • Passing by value creates a copy of the entire structure.

  • Passing by reference (using pointers) passes the address of the structure, allowing modifications to the original structure. Passing structures by reference is often preferred when dealing with large structures to avoid the overhead of copying.

Typedef

typedef in C can be used with structure definitions to create aliases for complex structure types, providing clearer and more concise code. This approach simplifies the declaration of structure variables and enhances code readability.

In the above example, typedef is used to create an alias Point for the structure struct { int x; int y; };. Then we can use the Point alias to declare variables p1 and p2 of the structure type.

Note that

is the same as

Unions

Union is a user-defined data type that allows storing different types of data in the same memory location. Unlike structures, where each member has its own memory space, all members of a union share the same memory location. This means that modifying one member may affect the value of other members.

In most cases, unions contain two or more items of different types, and you can reference only one member (and thus only one type) at a time. It's your responsibility as a programmer to ensure that you reference the data with the proper type. Attempting to access or interpret the data stored in a union with the wrong type can lead to logic errors, and the result is implementation-dependent.

Try to set floatValue to 100 after initialization of intValue, see the result.

Using a Union Containing Struct

Bitwise Operators

In computing, a bit (short for binary digit) is the smallest unit of data and can have one of two values: 0 or 1. Multiple bits are combined to represent more complex data types, such as integers, characters, or boolean values. On most systems, a sequence of eight bits forms a byte, the typical storage unit for a char variable.

Bitwise operators are used to perform manipulation and comparison operations on individual bits within binary representations of data.

Summary of bitwise operators

Bitwise Assignment Operators

Bitwise assignment operators combine bitwise operations with assignment, allowing for more concise code when performing bitwise operations on variables and assigning the result back to the same variable. These operators modify the value of a variable in-place using bitwise operations.

Bitwise operators are commonly used in low-level programming, device drivers, cryptography, and optimization algorithms. They are used to manipulate and extract specific bits from binary representations of data, perform bitwise arithmetic, and optimize memory usage.

Bit Fields

Bit fields are a feature that allows for the packing of data structures in a more memory-efficient manner. They enable the allocation of specific numbers of bits within a structure, providing precise control over memory usage and alignment.

To define, we use a syntax: type fieldName : width;, where type is the data type of the field, fieldName is the name of the field, and width is the number of bits allocated to the field.

It is important to note that due to their compact nature, individual bit fields are not assigned unique memory addresses like regular structure members. Attempting to take the address of a bit field can lead to errors or misleading results. For example,

You may see an error during compilation

Unnamed Bit Fields

Unnamed bit fields are bit fields that do not have a specified field name. They are used primarily for padding or alignment purposes within a structure.

Note that, in C, 0b is the prefix used to indicate that the following digits represent a binary number. In the above example, 32768 is represented by 0b1000000000000000

Enumeration Constants

Enumerations, often referred to as enums, are user-defined data types in C that consist of a set of named integer constants. They provide a way to create symbolic names for integral values, improving code readability and maintainability.

To number the days 1 to 7, uses

The example of using enumeration variable d in a for statement to print the day of the week from the array dayName.

Classwork - Week 10

Create a simple student record management system for this course using structures and enums. The program should allow users to perform the following tasks:

  1. Define a structure Student with the following fields:

    • Name (string)

    • Student ID (integer)

    • Grade (enum: A, B, C, D, F)

  2. Implement the following menu-driven functionalities:

    • Add a new student record

    • Display all student records

    • Delete a student record by student id

    • Exit

  3. Ensure input validation for user inputs (e.g., handle incorrect menu choices gracefully).

For simplicity, you can limit the number of student to be 10 students max.

Last updated