Portfolio Chapter 1
Portfolio Chapter 1
***********************************************************************************
***********
* file: portfolio chapter 1
* Description: A set of programs in c compiled from various sources such as
* websites, youtube videos and public github repositories including
* additional comments created by Debopratim Dutta with the help of
gemini.google.com
* The project aims to demonstrate various concepts of C programming along with some
theory
* for educational uses. This is not a project. I made the txt file just to
strengthen
* my concepts.
* Year: 2024
***********************************************************************************
**********/
/
***********************************************************************************
***********************/
* Program: to demonstrate malloc(), calloc(), realloc() and free()
* url: https://www.scholarhat.com/tutorial/c/dynamic-memory-allocation-in-c-
programming
https://www.geeksforgeeks.org/dynamic-memory-allocation-in-c-using-malloc-
calloc-free-and-realloc/
/
***********************************************************************************
***********************/
#include<stdio.h>
#include<stdlib.h>
int main()
{
int n,i,*ptr,sum=0;
printf("Enter the number of elements: ");
scanf("%d",&n);
ptr=(int*)malloc(n*sizeof(int)); //memory allocated using malloc
if(ptr==NULL)
{
printf("Unable to allocate memory");
exit(0);
}
printf("Enter elements of array: ");
for(i=0;i<n;++i)
{
scanf("%d",ptr+i);
sum+=*(ptr+i);
}
printf("Sum=%d",sum);
free(ptr);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
int main() {
int n, i, sum = 0;
void *ptr; // Using void* to store the allocated memory
/* Key Changes:
ptr as void*: The ptr variable is declared as void* to hold the raw memory address.
Explicit Castings: Whenever reading or writing values to the allocated memory, we
explicitly cast ptr to int* to ensure proper data interpretation:
scanf("%d", (int *)(ptr + i * sizeof(int)))
*(int *)(ptr + i * sizeof(int))
ptr + i * sizeof(int): This calculation adjusts the pointer to point to the correct
address of each integer element within the allocated block, as ptr doesn't
automatically increment by the size of int.
Remember:
While this code demonstrates void* usage, it's generally clearer and safer to cast
directly after malloc and use the appropriate pointer type for readability and type
safety
*/
OUTPUT:
Enter the number of elements: 5
Enter elements of the array: 10 20 30 40 50
Sum = 150
int main() {
int n, i, *ptr;
return 0;
}
OUTPUT:
Enter the number of elements: 5
Enter elements of the array: 10 20 30 40 50
The entered numbers in sequence: 10 20 30 40 50
OUTPUT:
Enter the number of elements to declare size required: 5
Addresses of previously allocated memory:
0x7fb3e4801000
0x7fb3e4801004
0x7fb3e4801008
0x7fb3e480100c
0x7fb3e4801010
#include <stdio.h>
#include <stdlib.h>
int main()
{
free(ptr);
}
return 0;
}
OUTPUT:
Enter number of elements: 5
Memory successfully allocated using calloc.
The elements of the array are: 1, 2, 3, 4, 5,
#include <stdio.h>
#include <stdlib.h>
int main()
{
int index = 0, i = 0, n,
*marks; // this marks pointer hold the base address
// of the block created
int ans;
marks = (int*)malloc(sizeof(
int)); // dynamically allocate memory using malloc
// check if the memory is successfully allocated by
// malloc or not?
if (marks == NULL) {
printf("memory cannot be allocated");
}
else {
// memory has successfully allocated
printf("Memory has been successfully allocated by "
"using malloc\n");
printf("\n marks = %pc\n",
marks); // print the base or beginning
// address of allocated memory
do {
printf("\n Enter Marks\n");
scanf("%d", &marks[index]); // Get the marks
printf("would you like to add more(1/0): ");
scanf("%d", &ans);
if (ans == 1) {
index++;
marks = (int*)realloc(
marks,
(index + 1)
* sizeof(
int)); // Dynamically reallocate
// memory by using realloc
// check if the memory is successfully
// allocated by realloc or not?
if (marks == NULL) {
printf("memory cannot be allocated");
}
else {
printf("Memory has been successfully "
"reallocated using realloc:\n");
printf(
"\n base address of marks are:%pc",
marks); ////print the base or
///beginning address of
///allocated memory
}
}
} while (ans == 1);
// print the marks of the students
for (i = 0; i <= index; i++) {
printf("marks of students %d are: %d\n ", i,
marks[i]);
}
free(marks);
}
return 0;
}
OUTPUT:
marks = 0000000000BB1420c
Enter Marks
10
would you like to add more(1/0): 1
Memory has been successfully reallocated using realloc:
--------------------------------
Process exited after 20.6 seconds with return value 0
Press any key to continue . . .
#include <stdio.h>
#include <stdlib.h>
int main() {
int n, i;
// Get the size of the array from the user
printf("Enter the number of elements: ");
scanf("%d", &n);
return 0;
}
OUTPUT:
--------------------------------
Process exited after 6.119 seconds with return value 0
Press any key to continue . . .
/
***********************************************************************************
******/
/*
SUMMARY:
syntax:
ptr=(cast-type*)malloc(byte-size)
ptr=(cast-type*)calloc(number, byte-size)
ptr=realloc(ptr, new-size)
free(ptr);
NOTES:
Stack and heap are two fundamental memory allocation areas used in programs. They
differ in several ways:
Allocation:
Stack: Static allocation. Memory size is fixed at compile time and managed by the
compiler.
Heap: Dynamic allocation. Memory is allocated and deallocated during program
execution as needed.
Structure:
Stack: LIFO (Last In, First Out) order. Think of a stack of plates - you add and
remove plates from the top.
Heap: No specific order. Memory is allocated in chunks of various sizes as
requested.
Accessibility:
Stack: Local variables within a function and function call arguments can access
stack memory. Thread-safe (data accessible only by the current thread).
Heap: Accessible from anywhere in the program. Not thread-safe (multiple threads
can access the same memory).
Lifetime:
Stack: Data exists only as long as the function is executing. When the function
returns, the memory is automatically freed.
Heap: Data persists until explicitly deallocated using language-specific methods
(e.g., free in C). Programmer is responsible for proper deallocation to avoid
memory leaks.
Use Cases:
Stack: Ideal for temporary data like function parameters, local variables, return
addresses. Faster access due to contiguous memory allocation.
Heap: Suitable for dynamically allocated data structures (e.g., linked lists,
trees) and objects with variable lifetimes.
When a memory block allocated using malloc or calloc is freed using free, the
memory becomes available for other allocations. However, any pointers that were
previously pointing to that memory location become dangling. They still hold the
address, but the data at that address is no longer guaranteed to be what the
program expects.
void createDanglingPointer() {
int *ptr;
{ // Create a local scope
int num = 10;
ptr = # // ptr points to local variable num
} // num goes out of scope here and memory is freed
// ptr is now a dangling pointer
printf("%d\n", *ptr); // Undefined behavior (value of freed memory)
}
In C and C++, free and delete are both used to deallocate memory, but they have key
differences:
free: Primarily used in C for memory allocated with functions like malloc, calloc,
and realloc. These functions request memory from the heap, a more flexible memory
space. free simply returns the memory block to the heap for potential future
allocations.
delete: Belongs to C++ and is specifically designed for memory allocated using the
new operator. The new operator not only allocates memory but also calls the
object's constructor (if it's a class object) to initialize the object. delete
deallocates the memory and also calls the object's destructor (if it's a class
object) to perform any necessary cleanup before returning the memory to the heap.
Usability:
free: Can only be used with memory allocated using malloc, calloc, or realloc.
Using free on memory allocated with new can lead to undefined behavior.
delete: Should only be used with memory allocated using the new operator. Using
delete on memory allocated with malloc won't call the destructor, potentially
causing memory leaks or issues with object cleanup.
The return type of both malloc and calloc in C is void*. This means they return a
generic pointer to an unspecified data type. Here's why:
Generic Allocation:
Memory Flexibility: malloc and calloc are designed to allocate raw blocks of memory
that can be used to store any kind of data. They don't need to know the specific
data type beforehand.
Wide Usage: By returning a void* pointer, they can be used for a wide range of
memory allocation needs, accommodating various data types.
Explicit Casting:
Type Safety: Since the compiler can't automatically assume the intended data type,
it's crucial for the programmer to explicitly cast the returned void* pointer to
the appropriate data type before using it.
*/