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?
- To store related information together (like student record, employee details, etc.).
- To handle real-life data models more efficiently.
- Allows grouping of different types (int, float, char[]) as a single unit.
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:
struct student→ new data type.stud1, stud2→ variables/objects of that structure.- Each object has its own copy of members (r_no, name, course, fees).
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:
- We created a structure
studentwith roll no, name & marks. s1is an object storing actual values.- We accessed members using the dot operator:
s1.r_no
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
- Use index to access specific student →
list[index] - Then use dot operator to access members →
list[i].member - Index starts from 0
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:
s1.r_no,s1.name,s1.fees→ accessed using dot operator.- Dot operator connects structure variable to its fields.
- Strings need
strcpy()or user input, cannot use '='.
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
- Structures to store student details
- Arrays of structures
- Looping and conditional statements
- Average calculation
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
- An array of structures stores details of multiple students.
- Marks are summed to compute the average.
- Each student's marks are compared with the average.
- Students are categorized as above or below average.
Key Points
- Structures group related data (name and marks).
- Arrays of structures handle multiple records.
- Logical comparison helps classify students based on performance.
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?
- C does not allow structure-to-structure comparison using
==or!=. - We must compare each member separately.
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:
- You can copy structures directly using
=. - You cannot compare entire structures directly.
- Compare specific members individually.
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:
- emp_id → 2 or 4 bytes (depends on system)
- name → 20 × 1 = 20 bytes
- salary → 8 bytes
- designation → 20 × 1 = 20 bytes
- experience → 4 bytes
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:
- Manual addition gives approximate size.
sizeofgives the exact size including padding.- Structure size may vary across compilers/platforms.
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
- The whole structure can be passed as a function argument.
- It is passed by value (copies are made).
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?
- Passing large structures by value is slow due to stack copying.
- Using a pointer only passes the address → faster execution.
- Functions can modify structure contents when passed as 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:
- Use . when accessing members via structure variable.
- Use -> when accessing via a structure pointer.
- Pointers allow faster passing and modification inside functions.
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
- Arrays behave normally inside structures.
- Access using
structureName.array[index]format.
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;
- Access nested fields using chain notation: outer.inner.member
- C allows at least 15 levels of nesting (C89), up to 63 levels (C99).
Key Points:
- Structures may contain arrays as members.
- Structures may also contain other structures.
- Members are accessed from outer → inner.
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.
- All members of a union share the same memory space.
- Storing a value in one member overwrites the previous value.
- The size of a union is equal to the size of its largest member.
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 |
|---|---|
struct struct_name {
|
union union_name {
|
Example:
struct student {
|
Example:
union student {
|
A structure variable is declared as:
struct student stud1; |
A union variable is declared as:
union student stud1; |
struct student stud1 = {01, "Rahul", "BCA", 45000};
|
union student stud1;
|
| 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?
- Store multiple Boolean values in a small memory space.
- Useful for hardware communication and status registers.
- Efficient representation for flags and bitwise operations.
- Improves code readability when handling bit-level data.
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
- Access using dot operator like normal structure members.
- To modify:
status.ring = 0;clears the ring bit. - If using pointer to structure → use
->operator.
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:
- Cannot take address of a bit-field.
- Bit-fields cannot be arrays.
- Bit ordering may differ between machines (platform-dependent).
- May have implementation-specific limitations.
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
- First item → value 0
- Next items increment automatically → 1, 2, 3 ...
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
- Enums convert to int automatically.
- Assigning int to enum may cause warning/error.
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?
- Makes code easier to understand
- Useful when porting programs across machines
- Allows descriptive names for data types
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
typedefonly renames a data type- Improves readability and maintainability
- Existing type name still remains valid
- Commonly used in structures, pointers, and complex type definitions