Introduction
Structure declaration in C defines a user-defined data type that groups related variables of different data types under a single name. Structures provide a way to organize and manage complex data by creating custom data types that model real-world entities with multiple attributes.
Key Concepts
Structure: User-defined data type grouping related variables Members: Individual variables within a structure Structure Tag: Name given to the structure type Structure Variable: Instance of a structure type Dot Operator: Used to access structure members Memory Layout: How structure members are arranged in memory
Basic Structure Declaration
1. Simple Structure Declaration
#include <stdio.h>
#include <string.h>
// Basic structure declaration
struct Student {
int rollNumber;
char name[50];
float marks;
char grade;
};
// Structure with different data types
struct Rectangle {
float length;
float width;
float area;
int color;
};
int main() {
printf("=== Basic Structure Declaration ===\n");
// Declare structure variables
struct Student student1;
struct Rectangle rect1;
// Initialize student data
student1.rollNumber = 101;
strcpy(student1.name, "John Doe");
student1.marks = 85.5;
student1.grade = 'A';
// Initialize rectangle data
rect1.length = 10.5;
rect1.width = 7.2;
rect1.area = rect1.length * rect1.width;
rect1.color = 1; // 1 for red, 2 for blue, etc.
// Display structure data
printf("Student Information:\n");
printf("Roll Number: %d\n", student1.rollNumber);
printf("Name: %s\n", student1.name);
printf("Marks: %.2f\n", student1.marks);
printf("Grade: %c\n", student1.grade);
printf("\nRectangle Information:\n");
printf("Length: %.2f\n", rect1.length);
printf("Width: %.2f\n", rect1.width);
printf("Area: %.2f\n", rect1.area);
printf("Color Code: %d\n", rect1.color);
return 0;
}
2. Structure Declaration with Initialization
#include <stdio.h>
#include <string.h>
// Employee structure
struct Employee {
int empId;
char name[50];
char department[30];
float salary;
int yearsOfService;
};
// Point structure for geometry
struct Point {
int x;
int y;
};
// Book structure
struct Book {
char title[100];
char author[50];
int pages;
float price;
int publishYear;
};
int main() {
printf("=== Structure Declaration with Initialization ===\n");
// Initialize during declaration
struct Employee emp1 = {1001, "Alice Johnson", "Engineering", 75000.0, 5};
struct Point origin = {0, 0};
struct Point corner = {10, 15};
struct Book book1 = {
"The C Programming Language",
"Dennis Ritchie",
274,
45.99,
1978
};
// Display initialized structures
printf("Employee Details:\n");
printf("ID: %d, Name: %s\n", emp1.empId, emp1.name);
printf("Department: %s\n", emp1.department);
printf("Salary: $%.2f\n", emp1.salary);
printf("Years of Service: %d\n", emp1.yearsOfService);
printf("\nPoint Coordinates:\n");
printf("Origin: (%d, %d)\n", origin.x, origin.y);
printf("Corner: (%d, %d)\n", corner.x, corner.y);
printf("\nBook Information:\n");
printf("Title: %s\n", book1.title);
printf("Author: %s\n", book1.author);
printf("Pages: %d\n", book1.pages);
printf("Price: $%.2f\n", book1.price);
printf("Published: %d\n", book1.publishYear);
return 0;
}
Structure with typedef
Using typedef for Cleaner Code
#include <stdio.h>
#include <string.h>
// Structure declaration with typedef
typedef struct {
char firstName[30];
char lastName[30];
int age;
char email[50];
} Person;
// Another typedef structure
typedef struct {
int day;
int month;
int year;
} Date;
// Structure using other structures
typedef struct {
int accountNumber;
Person accountHolder;
Date openingDate;
float balance;
char accountType[20];
} BankAccount;
// Function to display person information
void displayPerson(Person p) {
printf("Name: %s %s\n", p.firstName, p.lastName);
printf("Age: %d\n", p.age);
printf("Email: %s\n", p.email);
}
// Function to display date
void displayDate(Date d) {
printf("%02d/%02d/%04d", d.day, d.month, d.year);
}
// Function to display bank account
void displayBankAccount(BankAccount acc) {
printf("Account Number: %d\n", acc.accountNumber);
displayPerson(acc.accountHolder);
printf("Opening Date: ");
displayDate(acc.openingDate);
printf("\nBalance: $%.2f\n", acc.balance);
printf("Account Type: %s\n", acc.accountType);
}
int main() {
printf("=== Structure with typedef ===\n");
// Create person using typedef
Person person1;
strcpy(person1.firstName, "Emma");
strcpy(person1.lastName, "Wilson");
person1.age = 28;
strcpy(person1.email, "emma.wilson@email.com");
// Create date
Date today = {15, 10, 2023};
// Create bank account
BankAccount account1 = {
12345678,
{"Michael", "Brown", 35, "michael.brown@email.com"},
{10, 5, 2020},
15750.50,
"Savings"
};
printf("Person Information:\n");
displayPerson(person1);
printf("\nToday's Date: ");
displayDate(today);
printf("\n");
printf("\nBank Account Information:\n");
displayBankAccount(account1);
return 0;
}
Array of Structures
Working with Multiple Structure Instances
#include <stdio.h>
#include <string.h>
// Product structure
typedef struct {
int productId;
char productName[50];
float price;
int quantity;
char category[30];
} Product;
// Function to display product
void displayProduct(Product p) {
printf("ID: %-5d Name: %-20s Price: $%-8.2f Qty: %-5d Category: %s\n",
p.productId, p.productName, p.price, p.quantity, p.category);
}
// Function to find product by ID
int findProductById(Product products[], int size, int id) {
for (int i = 0; i < size; i++) {
if (products[i].productId == id) {
return i;
}
}
return -1;
}
// Function to calculate total inventory value
float calculateTotalValue(Product products[], int size) {
float total = 0;
for (int i = 0; i < size; i++) {
total += products[i].price * products[i].quantity;
}
return total;
}
int main() {
printf("=== Array of Structures ===\n");
// Array of products
Product inventory[5] = {
{101, "Laptop", 899.99, 15, "Electronics"},
{102, "Mouse", 25.50, 50, "Electronics"},
{103, "Desk Chair", 149.99, 8, "Furniture"},
{104, "Notebook", 3.25, 100, "Stationery"},
{105, "Monitor", 299.99, 12, "Electronics"}
};
int inventorySize = 5;
// Display all products
printf("Product Inventory:\n");
printf("%-5s %-20s %-10s %-7s %-15s\n", "ID", "Name", "Price", "Qty", "Category");
printf("---------------------------------------------------------------\n");
for (int i = 0; i < inventorySize; i++) {
displayProduct(inventory[i]);
}
// Find specific product
int searchId = 103;
int index = findProductById(inventory, inventorySize, searchId);
if (index != -1) {
printf("\nFound product with ID %d:\n", searchId);
displayProduct(inventory[index]);
}
// Calculate total inventory value
float totalValue = calculateTotalValue(inventory, inventorySize);
printf("\nTotal Inventory Value: $%.2f\n", totalValue);
// Update product quantity
inventory[1].quantity += 25; // Add 25 mice to inventory
printf("Updated Mouse quantity: %d\n", inventory[1].quantity);
return 0;
}
Advanced Structure Declarations
1. Structure with Function Pointers
#include <stdio.h>
#include <string.h>
// Structure with function pointers
typedef struct {
char name[50];
int (*add)(int, int);
int (*subtract)(int, int);
void (*display)(const char*);
} Calculator;
// Function implementations
int addition(int a, int b) {
return a + b;
}
int subtraction(int a, int b) {
return a - b;
}
void displayMessage(const char* msg) {
printf("Calculator: %s\n", msg);
}
// Structure representing a geometric shape
typedef struct {
char shapeName[20];
float (*calculateArea)(float, float);
float (*calculatePerimeter)(float, float);
} Shape;
// Shape calculation functions
float rectangleArea(float length, float width) {
return length * width;
}
float rectanglePerimeter(float length, float width) {
return 2 * (length + width);
}
int main() {
printf("=== Structure with Function Pointers ===\n");
// Initialize calculator structure
Calculator calc = {
"Basic Calculator",
addition,
subtraction,
displayMessage
};
// Use calculator
calc.display("Starting calculations");
int sum = calc.add(15, 25);
int diff = calc.subtract(30, 12);
printf("Addition result: %d\n", sum);
printf("Subtraction result: %d\n", diff);
// Initialize shape structure
Shape rectangle = {
"Rectangle",
rectangleArea,
rectanglePerimeter
};
printf("\nShape: %s\n", rectangle.shapeName);
float area = rectangle.calculateArea(8.0, 5.0);
float perimeter = rectangle.calculatePerimeter(8.0, 5.0);
printf("Area: %.2f\n", area);
printf("Perimeter: %.2f\n", perimeter);
return 0;
}
2. Self-Referential Structures
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Self-referential structure for linked list
typedef struct Node {
int data;
struct Node* next;
} Node;
// Tree node structure
typedef struct TreeNode {
int value;
struct TreeNode* left;
struct TreeNode* right;
} TreeNode;
// Function to create new node
Node* createNode(int data) {
Node* newNode = malloc(sizeof(Node));
if (newNode != NULL) {
newNode->data = data;
newNode->next = NULL;
}
return newNode;
}
// Function to display linked list
void displayList(Node* head) {
Node* current = head;
printf("List: ");
while (current != NULL) {
printf("%d ", current->data);
current = current->next;
}
printf("\n");
}
// Function to free linked list
void freeList(Node* head) {
Node* current = head;
while (current != NULL) {
Node* next = current->next;
free(current);
current = next;
}
}
int main() {
printf("=== Self-Referential Structures ===\n");
// Create linked list
Node* head = createNode(10);
head->next = createNode(20);
head->next->next = createNode(30);
head->next->next->next = createNode(40);
displayList(head);
// Add node at beginning
Node* newHead = createNode(5);
newHead->next = head;
head = newHead;
printf("After adding 5 at beginning:\n");
displayList(head);
// Clean up memory
freeList(head);
printf("Memory freed\n");
return 0;
}
3. Bit Fields in Structures
#include <stdio.h>
// Structure with bit fields
typedef struct {
unsigned int day : 5; // 5 bits (0-31)
unsigned int month : 4; // 4 bits (0-15)
unsigned int year : 12; // 12 bits (0-4095)
} PackedDate;
// Status flags using bit fields
typedef struct {
unsigned int isActive : 1;
unsigned int isVisible : 1;
unsigned int isEditable : 1;
unsigned int isSelected : 1;
unsigned int reserved : 4; // Reserved for future use
} StatusFlags;
// System configuration
typedef struct {
unsigned int cpuType : 3; // CPU type (0-7)
unsigned int memorySize : 5; // Memory size code (0-31)
unsigned int hasSound : 1; // Sound capability
unsigned int hasNetwork : 1; // Network capability
unsigned int osType : 3; // OS type (0-7)
unsigned int unused : 19; // Unused bits
} SystemConfig;
int main() {
printf("=== Bit Fields in Structures ===\n");
// PackedDate example
PackedDate today;
today.day = 15;
today.month = 10;
today.year = 2023;
printf("Packed Date: %d/%d/%d\n", today.day, today.month, today.year);
printf("Size of PackedDate: %zu bytes\n", sizeof(PackedDate));
// StatusFlags example
StatusFlags status = {0}; // Initialize all to 0
status.isActive = 1;
status.isVisible = 1;
status.isEditable = 0;
status.isSelected = 1;
printf("\nStatus Flags:\n");
printf("Active: %s\n", status.isActive ? "Yes" : "No");
printf("Visible: %s\n", status.isVisible ? "Yes" : "No");
printf("Editable: %s\n", status.isEditable ? "Yes" : "No");
printf("Selected: %s\n", status.isSelected ? "Yes" : "No");
printf("Size of StatusFlags: %zu bytes\n", sizeof(StatusFlags));
// SystemConfig example
SystemConfig config;
config.cpuType = 2; // Intel
config.memorySize = 8; // 8GB
config.hasSound = 1; // Yes
config.hasNetwork = 1; // Yes
config.osType = 3; // Linux
config.unused = 0;
printf("\nSystem Configuration:\n");
printf("CPU Type: %d\n", config.cpuType);
printf("Memory Size Code: %d\n", config.memorySize);
printf("Sound: %s\n", config.hasSound ? "Yes" : "No");
printf("Network: %s\n", config.hasNetwork ? "Yes" : "No");
printf("OS Type: %d\n", config.osType);
printf("Size of SystemConfig: %zu bytes\n", sizeof(SystemConfig));
return 0;
}
Memory Layout and Alignment
Understanding Structure Memory Layout
#include <stdio.h>
#include <stddef.h>
// Structure without padding consideration
struct UnalignedStruct {
char c;
int i;
char c2;
double d;
};
// Structure with better alignment
struct AlignedStruct {
char c;
char c2;
int i;
double d;
};
// Packed structure (compiler-specific)
#pragma pack(push, 1)
struct PackedStruct {
char c;
int i;
char c2;
double d;
};
#pragma pack(pop)
int main() {
printf("=== Structure Memory Layout ===\n");
// Display sizes
printf("Structure Sizes:\n");
printf("UnalignedStruct: %zu bytes\n", sizeof(struct UnalignedStruct));
printf("AlignedStruct: %zu bytes\n", sizeof(struct AlignedStruct));
printf("PackedStruct: %zu bytes\n", sizeof(struct PackedStruct));
// Display member offsets for UnalignedStruct
printf("\nUnalignedStruct member offsets:\n");
printf("c offset: %zu\n", offsetof(struct UnalignedStruct, c));
printf("i offset: %zu\n", offsetof(struct UnalignedStruct, i));
printf("c2 offset: %zu\n", offsetof(struct UnalignedStruct, c2));
printf("d offset: %zu\n", offsetof(struct UnalignedStruct, d));
// Display member offsets for AlignedStruct
printf("\nAlignedStruct member offsets:\n");
printf("c offset: %zu\n", offsetof(struct AlignedStruct, c));
printf("c2 offset: %zu\n", offsetof(struct AlignedStruct, c2));
printf("i offset: %zu\n", offsetof(struct AlignedStruct, i));
printf("d offset: %zu\n", offsetof(struct AlignedStruct, d));
// Display member offsets for PackedStruct
printf("\nPackedStruct member offsets:\n");
printf("c offset: %zu\n", offsetof(struct PackedStruct, c));
printf("i offset: %zu\n", offsetof(struct PackedStruct, i));
printf("c2 offset: %zu\n", offsetof(struct PackedStruct, c2));
printf("d offset: %zu\n", offsetof(struct PackedStruct, d));
return 0;
}
Important Points
- Structure declaration creates a new data type, not a variable
- Structure variables must be declared separately after structure definition
- Member access uses dot operator (.) for structure variables
- Initialization can be done during declaration or separately
- typedef simplifies structure usage by creating type aliases
- Memory alignment may add padding between members
- Bit fields allow precise control over memory usage
- Self-referential structures enable dynamic data structures
Best Practices
- Use meaningful names for structures and members
- Group related data logically in structures
- Consider memory alignment for efficiency
- Use typedef to simplify complex structure declarations
- Initialize all members to avoid garbage values
- Document structure purpose and member meanings
- Use consistent naming conventions throughout code
- Consider bit fields for flag storage and memory optimization
Summary
Structure declaration in C creates user-defined data types that group related variables under a single name. Structures can contain different data types, function pointers, and even references to themselves. Proper structure design with consideration for memory layout, initialization methods, and naming conventions is essential for creating maintainable and efficient C programs.
Part of BCA Programming with C Course (UGCOA22J201)