Module 4: Chapter 7 - Structures

Structures in C

A Structure is a user-defined data type in C that allows grouping of variables with different data types under a single name. It helps store logically related data together. It is different from an array because arrays store only one data type, whereas structures can hold multiple data types at once.

Why do we need Structures?

Structure Declaration Syntax:

struct structure_name {
  data_type member1;
  data_type member2;
  ...;
};

Note: Declaration ends with a semicolon.

Example:

struct student {
  int r_no;
  char name[20];
  char course[20];
  float fees;
};

After declaring a structure type, we must create a variable (object) to use it.

Creating Structure Variables:

struct student stud1; // stud1 is a structure variable

// You can also declare variables inside structure itself
struct student {
  int r_no;
  char name[20];
  char course[20];
  float fees;
} stud1, stud2;

Key Understanding:

Student Example:

#include <stdio.h>
struct student {
  int r_no;
  char name[20];
  float marks;
};

int main() {
  struct student s1 = {101, "Raj", 89.5};

  printf("Roll No: %d\n", s1.r_no);
  printf("Name: %s\n", s1.name);
  printf("Marks: %.2f\n", s1.marks);
  return 0;
}

Output:

        Roll No: 101
        Name   : Raj
        Marks  : 89.50
      

Explanation:

Arrays of Structures

We can create an array of structures when we want to store multiple records of the same structure type (like multiple students). First define a structure, then declare an array of it.

Example Structure:

struct student {
  char name[30];
  int age;
  float marks;
};

struct student list[5]; // array of 5 students

Each element in list represents a separate student.

Accessing Elements

list[0].age = 20; // Assign value
printf("%s", list[1].name); // Read value
list[2].name[0] = 'A'; // First char of name of 3rd student

Small Example Program

#include <stdio.h>

struct student {
  char name[30];
  int age;
  float marks;
};

int main(){
  struct student list[3] = {{"Raj", 18, 85.5}, {"Reena", 19, 90.2}, {"Sahana", 20, 78.0}};

  printf("%s - %d - %.2f", list[1].name, list[1].age, list[1].marks);
  return 0;
}

Example Program: Read & Display Student Details

#include <stdio.h>
struct student {
  int rnum;
  char name[20];
  int marks;
} s[60];

int main(){
  int i, n;
  printf("Enter number of students: ");
  scanf("%d", &n);

  printf("\nEnter Roll No, Name, Marks:\n");
  for(i=1; i<=n; i++){
    printf("Student %d details:\n", i);
    scanf("%d %s %d", &s[i].rnum, s[i].name, &s[i].marks);
  }

  printf("\nRoll_No\tName\tMarks\n");
  for(i=1; i<=n; i++)
    printf("%d\t%s\t%d\n", s[i].rnum, s[i].name, s[i].marks);

  return 0;
}

Output:

Enter number of students: 5
Roll_No Name Marks
14 Ironman 89
15 Thor 55
11 Antman 45
12 Panther 35
10 Pakoda 68

Accessing Members of a Structure

Once a structure variable is declared, we can access its individual members using the dot operator ( . ). The dot symbol connects the structure variable with its members.

Syntax:

structure_variable.member_name;

Example (Assigning Values):

stud1.r_no = 01;
strcpy(stud1.name, "Raj"); // strings require strcpy()
strcpy(stud1.course, "BCA");
stud1.fees = 45000;

Note: Strings cannot be assigned using '=' directly. We use strcpy() instead.

Taking Input from User:

scanf("%d", &stud1.r_no);
scanf("%s", stud1.name); // no & for string, because name is already a pointer

Printing Structure Members:

printf("%s", stud1.course);
printf("%f", stud1.fees);

Student Example Program:

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

struct student {
  int r_no;
  char name[20];
  float fees;
};

int main() {
  struct student s1;

  printf("Enter Roll No: ");
  scanf("%d", &s1.r_no);

  printf("Enter Name: ");
  scanf("%s", s1.name);

  s1.fees = 45000; // direct assigning

  printf("\nStudent Details:\n");
  printf("Roll No: %d\n", s1.r_no);
  printf("Name: %s\n", s1.name);
  printf("Fees: %.2f\n", s1.fees);
  return 0;
}

Explanation:

Example Program: C Program Using Structure to Analyze Student Marks

Problem Statement

Write a C program using structure to read the marks of N students, compute the average marks, and list students scoring above and below the average.

Concept Used

Structure Definition

A structure is used to store the student name and marks together.

struct student {
  char name[30];
  float marks;
};

C Program

#include <stdio.h>

struct student {
  char name[30];
  float marks;
};

int main() {
  int n, i;
  float sum = 0, avg;
  struct student s[50];

  printf("Enter number of students: ");
  scanf("%d", &n);

  for(i = 0; i < n; i++) {
    printf("Enter name of student %d: ", i + 1);
    scanf("%s", s[i].name);
    printf("Enter marks of student %d: ", i + 1);
    scanf("%f", &s[i].marks);
    sum = sum + s[i].marks;
  }

  avg = sum / n;
  printf("\nAverage Marks = %.2f\n", avg);

  printf("\nStudents scoring ABOVE average:\n");
  for(i = 0; i < n; i++) {
    if(s[i].marks > avg)
      printf("%s : %.2f\n", s[i].name, s[i].marks);
  }

  printf("\nStudents scoring BELOW average:\n");
  for(i = 0; i < n; i++) {
    if(s[i].marks < avg)
      printf("%s : %.2f\n", s[i].name, s[i].marks);
  }

  return 0;
}

Output

        Enter number of students: 6
        Enter name of student 1: batman
        Enter marks of student 1: 70
        Enter name of student 2: superman
        Enter marks of student 2: 88
        Enter name of student 3: ironman
        Enter marks of student 3: 85
        Enter name of student 4: mangoMan
        Enter marks of student 4: 32
        Enter name of student 5: kingPin
        Enter marks of student 5: 22
        Enter name of student 6: Jack
        Enter marks of student 6: 76
        Average Marks = 62.17

        Students scoring ABOVE average:
        batman : 70.00
        superman : 88.00
        ironman : 85.00
        Jack : 76.00

        Students scoring BELOW average:
        mangoMan : 32.00
        kingPin : 22.00\n
      

Explanation

Key Points

Copying and Comparing Structures

In C, you can directly assign one structure variable to another only if both are of the same structure type. However, structures cannot be compared directly using operators like ==. Instead, you must compare individual members manually.

Copying Structures

To copy values of one structure into another:

stud2 = stud1; // Valid only when both are same structure type

Why Direct Comparison is Not Allowed?

Example - Comparing Structure Members

if(stud1.fees > stud2.fees) // comparing specific member
  printf("Student 1 has higher fees.");

Student Example Program:

#include <stdio.h>

struct student {
  int r_no;
  float fees;
};

int main() {
  struct student stud1 = {1, 45000};
  struct student stud2;

  stud2 = stud1; // copying structure

  if(stud1.fees == stud2.fees)
    printf("Fees are same.\n");

  if(stud1.fees > stud2.fees)
    printf("stud1 has higher fees.");
  else
    printf("stud2 has higher or equal fees.");

  return 0;
}

Key Points:

Finding the Size of Structures

The size (memory required) for a structure depends on the size of all its members. In C, we can find the size of a structure using two methods.

1. Simple Addition Method

Add the size of all data members manually. Example:

struct Employee {
  int emp_id;
  char name[20];
  double salary;
  char designation[20];
  float experience;
};

Output:

Calculating size:

Total Size = 2 + 20 + 8 + 20 + 4 = 54 bytes (without alignment/padding)

Note: In real systems size may increase due to padding/alignment.

2. Using sizeof Operator

Easiest and most accurate way:

sizeof(struct_name); // gives size in bytes

Program:

#include <stdio.h>
struct employee {
  int emp_id;
  char name[10];
  double salary;
  char designation[20];
  float experience;
};

int main(){
  struct employee e;
  printf("%d", sizeof(e));
  return 0;
}

Key Points:

Structures and Functions

A function can access structure members in three ways:


1. Passing Individual Members

Individual members can be passed directly to a function using the dot operator (.).

#include<stdio.h>
typedef struct {
  int x;
  int y;
} POINT;

void display(int, int);

void main(){
  POINT p1 = {2, 3};
  display(p1.x, p1.y);
}

void display(int a, int b){
  printf("The coordinates of the point are: %d %d", a, b);
}

Output: The coordinates of the point are: 2 3


2. Passing the Entire Structure

Syntax:

struct struct_name func_name(struct struct_name struct_var);

Example program:

#include<stdio.h>
typedef struct {
  int x;
  int y;
} POINT;

void display(POINT);

void main(){
  POINT p1 = {2, 3};
  display(p1);
}

void display(POINT p){
  printf("The coordinates of the point are: %d %d", p.x, p.y);
}

3. Passing Structure Through Pointers

Pointer can be used to access structure members. Members are accessed using arrow operator ( -> ).

Declaration Example:

struct student *ptr_stud, stud;

Accessing Members:

(*ptr_stud).roll_no;
ptr_stud->roll_no = 01;   // Recommended way

Example Program:

#include<stdio.h>
struct student{
  int r_no;
  char name[20];
  char course[20];
  float fees;
};

void main(){
  struct student stud1, *ptr_stud1;
  ptr_stud1 = &stud1;

  ptr_stud1->r_no = 01;
  strcpy(ptr_stud1->name, "Raj");
  strcpy(ptr_stud1->course, "Btech");
  ptr_stud1->fees = 45000;

  printf("DETAILS OF STUDENT");
  printf("\nROLL NUMBER = %d", ptr_stud1->r_no);
  printf("\nNAME = %s", ptr_stud1->name);
  printf("\nCOURSE = %s", ptr_stud1->course);
  printf("\nFEES = %f", ptr_stud1->fees);
}

Structure Pointers

C allows pointers to structures like any other data type. They are especially useful for efficient function passing (call by reference) and for creating dynamic data structures such as linked lists.

Declaring a Structure Pointer

Use * before the variable name to declare a structure pointer.

struct addr *addr_pointer; // pointer to structure of type addr

Why Use Structure Pointers?

Assigning Address to Structure Pointer

struct bal {
  float balance;
  char name[80];
} person;

struct bal *p; // pointer declaration
p = &person; // pointer stores address of structure

Accessing Structure Members

When using structure variables → dot operator (.)
When using structure pointers → arrow operator (->)

(*p).balance; // using dereference notation
p->balance; // preferred way (arrow operator)

Program Using Structure Pointer

Software timer using structure pointers and functions.

#include <stdio.h>
#define DELAY 128000

struct my_time {
  int hours;
  int minutes;
  int seconds;
};

void display(struct my_time *t);
void update(struct my_time *t);
void delay(void);

int main(void){
  struct my_time systime = {0,0,0};

  for(;;){
    update(&systime); // pass structure address
    display(&systime);
  }
  return 0;
}

void update(struct my_time *t){
  t->seconds++;
  if(t->seconds==60){
    t->seconds=0; t->minutes++;
    if(t->minutes==60){
      t->minutes=0; t->hours++;
    }
    if(t->hours==24) t->hours=0;
  }
  delay();
}

void display(struct my_time *t){
  printf("%02d:", t->hours);
  printf("%02d:", t->minutes);
  printf("%02d\n", t->seconds);
}

void delay(void){
  long int i;
  for(i=1; i<DELAY; ++i);
}

Key Takeaways:

Arrays and Structures within Structures

Structure members can be simple data types (int, float) or aggregate types like arrays and nested structures. Arrays inside structures behave like normal arrays.

Structure Containing an Array

struct x {
  int a[10][10]; // 10x10 integer array
  float b;
} y;

// Accessing array element
y.a[3][7]; // element at row 3, column 7

Nested Structures

A structure inside another structure is known as a nested structure.

struct emp {
  struct addr address; // nested structure
  float wage;
} worker;

// Assigning nested member
worker.address.zip = 93456;

Key Points:

Union

Definition

A union is a user-defined data type in C that allows storing different data types in the same memory location. Unlike structures, only one member of a union can contain a value at any given time.

Syntax

union union_name {
  data_type member1;
  data_type member2;
  ...
};

Declaring a Union

union sample {
  int x;
  float y;
  char ch;
};

Accessing Members

Union members are accessed using the dot (.) operator, similar to structures.

union sample u;
u.x = 10;
u.y = 3.14;  // overwrites value of x

Initialization

Only the first member of a union can be initialized at the time of declaration.

Example Program

#include <stdio.h>

typedef struct { int x, y; } POINT1;
typedef union { int x; int y; } POINT2;

int main() {
  POINT1 P1 = {2, 3};
  POINT2 P2;

  P2.x = 4;
  P2.y = 5;  // overwrites x

  printf("P1 = %d %d\n", P1.x, P1.y);
  printf("P2 = %d %d\n", P2.x, P2.y);
  return 0;
}

Output

P1 = 2 3
P2 = 5 5

Conclusion

In a union, all members share the same memory location. Therefore, changing the value of one member affects all other members. Unions are useful when memory optimization is required.

Differences between Structure and Union

Structure Union
  • Defined using: struct keyword
Syntax:
struct struct_name {
  data_type var_name;
  data_type var_name;
};
  • Defined using: union keyword
Syntax:
union union_name {
  data_type var_name;
  data_type var_name;
};
Example:
struct student {
  int r_no;
  char name[20];
  char course[20];
  float fees;
};
Example:
union student {
  int r_no;
  char name[20];
  char course[20];
  float fees;
};
A structure variable is declared as:
struct student stud1;
A union variable is declared as:
union student stud1;
  • All members can be initialized at once.
struct student stud1 = {01, "Rahul", "BCA", 45000};
  • Only one member can store a valid value at a time.
union student stud1;
stud1.r_no = 01;
stud1.name = "Rahul";
stud1.course = "BCA";
stud1.fees = 45000;
Each member has its own separate storage. All members share a single memory space.
Size = sum of all member sizes. Size = size of the largest member.
Changing one member does not affect others. Changing one member overwrites other member values.

Bit-Fields in C

Bit-fields allow accessing and manipulating specific bits inside a structure. Useful when dealing with limited memory, hardware-related programming, encryption, or when multiple Boolean values need to be packed efficiently.

Why Use Bit-fields?

Syntax

type member_name : bit_length;
// Type must be int, unsigned, signed or _Bool (C99)

Structure Bit-Field Example

struct status_type {
  unsigned delta_cts : 1;
  unsigned delta_dsr : 1;
  unsigned tr_edge : 1;
  unsigned delta_rec: 1;
  unsigned cts : 1;
  unsigned dsr : 1;
  unsigned ring : 1;
  unsigned rec_line : 1;
} status;

Status Bit-Meaning Table

Bit Meaning
0 Change in clear-to-send line
1 Change in data-set-ready
2 Trailing edge detected
3 Change in receive line
4 Clear-to-send
5 Data-set-ready
6 Telephone ringing
7 Received signal

Usage Example

status = get_port_status();
if(status.cts) printf("clear to send");
if(status.dsr) printf("data ready");

Assigning Bit-Field Values

Unnamed Bit-Fields

Used to skip unused bits.

struct status_type {
  unsigned : 4; // skip first 4 bits
  unsigned cts : 1;
  unsigned dsr : 1;
} status;

Mixing Bit-Fields with Normal Members

struct emp {
  struct addr address;
  float pay;
  unsigned lay_off : 1;
  unsigned hourly : 1;
  unsigned deductions : 3;
};

Restrictions:

Enumerated Data Types (enum)

Enumeration is a user-defined data type that assigns names to integer constants. It increases program readability and restricts values to a defined set.

Definition Syntax

enum enum_name { identifier1, identifier2, ..., identifierN };

Example

enum COLORS {RED, BLUE, BLACK, GREEN, YELLOW, PURPLE, WHITE};

Default Assigned Values

Explicit Value Assignment

enum COLORS {RED=2, BLUE, BLACK=5, GREEN=7, YELLOW, PURPLE, WHITE=15};

Declaring Enum Variables

enum COLORS bg_color; enum COLORS {RED, BLUE, BLACK} bg, fore;

Using typedef With enum

typedef enum COLORS color;
color forecolor = RED;

Assigning Enum Values

enum COLORS bg_color, border_color;
bg_color = BLACK;
border_color = bg_color;

Type Conversion

enum COLORS c;
c = (enum COLORS)(BLACK + WHITE); // Casting required

Comparison & Switch Use

enum {RED, BLUE, BLACK, GREEN} bg_color;
switch(bg_color){
  case RED:
  case BLUE:
  case GREEN: printf("Primary color"); break;
  default: printf("Not primary");
}

Input/Output

Enum values are printed as integers using printf.

enum COLORS c = RED;
printf("Color = %d", c); // Output: 0

typedef in C

typedef is used to give a new name (alias) to an existing data type. It does not create a new type - it only renames an existing one. This helps make programs more readable and portable.

General Syntax

typedef existing_type new_name;

Why Use typedef?

Example

typedef float balance;
balance over_due; // same as float over_due;

Now balance is another name for float. typedef names can be reused to create more readable type aliases.

typedef balance overdraft;
overdraft amt; // also a float type variable

Key Points