[go: up one dir, main page]

0% found this document useful (0 votes)
29 views10 pages

Portfolio Chapter 1

Uploaded by

duttapratim515
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
29 views10 pages

Portfolio Chapter 1

Uploaded by

duttapratim515
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 10

/

***********************************************************************************
***********
* 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/
/
***********************************************************************************
***********************/

// malloc sample code 1

#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;
}

//same code can also be written as:

#include <stdio.h>
#include <stdlib.h>
int main() {
int n, i, sum = 0;
void *ptr; // Using void* to store the allocated memory

printf("Enter the number of elements: ");


scanf("%d", &n);

ptr = malloc(n * sizeof(int)); // Allocate memory using malloc, returning void*


if (ptr == NULL) {
printf("Unable to allocate memory");
exit(0);
}

printf("Enter elements of array: ");


for (i = 0; i < n; ++i) {
scanf("%d", (int *)(ptr + i * sizeof(int))); // Cast to int* before input
sum += *(int *)(ptr + i * sizeof(int)); // Cast to int* for addition
}

printf("Sum = %d", sum);


free(ptr); // Deallocate memory
return 0;
}

/* 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

// malloc sample code 2


// the same code but the elements will be printed this time in sequence
#include <stdio.h>
#include <stdlib.h>

int main() {
int n, i, *ptr;

printf("Enter the number of elements: ");


scanf("%d", &n);

// Allocate memory using malloc with error handling


ptr = (int*)malloc(n * sizeof(int));
if (ptr == NULL) {
printf("Unable to allocate memory\n");
exit(1); // Indicate abnormal termination
}

printf("Enter elements of array: ");


for (i = 0; i < n; i++) {
scanf("%d", ptr + i);
}

printf("The entered numbers in sequence:\n");


for (i = 0; i < n; i++) {
printf("%d ", *(ptr + i)); // Print element using dereferencing
}
printf("\n"); // Add a newline for better formatting

// Free memory using free


free(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

//you can input each element in newline or space, doesn't matter

// calloc sample code 1


#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*)calloc(n,sizeof(int)); //memory allocated using calloc
if(ptr==NULL)
{
printf("Unable to allocate memory");
exit(0);
}
printf("Enter the elements of array: ");
for(i=0;i<n;++i)
{
scanf("%d",ptr+i);
sum+=*(ptr+i);
}
printf("Sum=%d",sum);
free(ptr);
return 0;
}

OUTPUT: same as above

// realloc sample code 1


#include <stdio.h>
#include <stdlib.h>
int main()
{
int *ptr, i , n1, n2;
printf("Enter the number of elements to declare size required: ");
scanf("%d", &n1);
ptr = (int*) malloc(n1 * sizeof(int)); //memory allocated using malloc()
printf("Addresses of previously allocated memory:\n");
for(i = 0; i < n1; ++i)
{
printf("%p\n",ptr + i);
}
printf("\nEnter the number of elements to declare the new size required: ");
scanf("%d", &n2);

// rellocating the memory


ptr = realloc(ptr, n2 * sizeof(int));
printf("Addresses of newly allocated memory:\n");
for(i = 0; i < n2; ++i)
{
printf("%p\n", ptr + i);
}
free(ptr);
return 0;
}

OUTPUT:
Enter the number of elements to declare size required: 5
Addresses of previously allocated memory:
0x7fb3e4801000
0x7fb3e4801004
0x7fb3e4801008
0x7fb3e480100c
0x7fb3e4801010

Enter the number of elements to declare the new size required: 7


Addresses of newly allocated memory:
0x7fb3e4801000
0x7fb3e4801004
0x7fb3e4801008
0x7fb3e480100c
0x7fb3e4801010
0x7fb3e4801014
0x7fb3e4801018

// realloc sample code 2:

#include <stdio.h>
#include <stdlib.h>

int main()
{

// This pointer will hold the


// base address of the block created
int* ptr;
int n, i;
// Get the number of elements for the array
n = 5;
printf("Enter number of elements: %d\n", n);

// Dynamically allocate memory using calloc()


ptr = (int*)calloc(n, sizeof(int));

// Check if the memory has been successfully


// allocated by malloc or not
if (ptr == NULL) {
printf("Memory not allocated.\n");
exit(0);
}
else {

// Memory has been successfully allocated


printf("Memory successfully allocated using calloc.\n");

// Get the elements of the array


for (i = 0; i < n; ++i) {
ptr[i] = i + 1;
}

// Print the elements of the array


printf("The elements of the array are: ");
for (i = 0; i < n; ++i) {
printf("%d, ", ptr[i]);
}

// Get the new size for the array


n = 10;
printf("\n\nEnter the new size of the array: %d\n", n);

// Dynamically re-allocate memory using realloc()


ptr = (int*)realloc(ptr, n * sizeof(int));

// Memory has been successfully allocated


printf("Memory successfully re-allocated using realloc.\n");

// Get the new elements of the array


for (i = 5; i < n; ++i) {
ptr[i] = i + 1;
}

// Print the elements of the array


printf("The elements of the array are: ");
for (i = 0; i < n; ++i) {
printf("%d, ", ptr[i]);
}

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,

Enter the new size of the array: 10


Memory successfully re-allocated using realloc.
The elements of the array are: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,

//realloc sample code3:

#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:

Memory has been successfully allocated by using malloc

marks = 0000000000BB1420c

Enter Marks
10
would you like to add more(1/0): 1
Memory has been successfully reallocated using realloc:

base address of marks are:0000000000BB1420c


Enter Marks
15
would you like to add more(1/0): 1
Memory has been successfully reallocated using realloc:

base address of marks are:0000000000BB1420c


Enter Marks
25
would you like to add more(1/0): 1
Memory has been successfully reallocated using realloc:

base address of marks are:0000000000BB1420c


Enter Marks
78
would you like to add more(1/0): 0
marks of students 0 are: 10
marks of students 1 are: 15
marks of students 2 are: 25
marks of students 3 are: 78

--------------------------------
Process exited after 20.6 seconds with return value 0
Press any key to continue . . .

// create an array using dynamic memory allocation

#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);

// Allocate memory for the array using malloc


int *arr = (int*)malloc(n * sizeof(int));

// Check if memory allocation was successful


if (arr == NULL) {
printf("Memory allocation failed!\n");
return 1;
}

// Get input for the elements of the array


printf("Enter elements of the array: ");
for (i = 0; i < n; ++i) {
scanf("%d", arr + i); // Equivalent to scanf("%d", &arr[i]);
}

// Print the elements of the array


printf("The array elements are: ");
for (i = 0; i < n; ++i) {
printf("%d ", arr[i]);
}
printf("\n");

// Deallocate the memory using free


free(arr);

return 0;
}

OUTPUT:

Enter the number of elements: 4


Enter elements of the array: 2 4 6 8
The array elements are: 2 4 6 8

--------------------------------
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);

// note that *(ptr+i) is same as ptr[i]


// some concepts to take care about are -
// static and dynamic memory allocation
// stack and heap memory segment

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.

Consequences of Dangling Pointers:

Segmentation Fault: Dereferencing a dangling pointer (accessing the data it points


to using the asterisk *) can result in a segmentation fault. This crash occurs
because the program tries to access memory that it's no longer authorized to use.
Unexpected Behavior: The program might read or write garbage data from the freed
memory location, leading to unpredictable program behavior and potential security
vulnerabilities.

void createDanglingPointer() {
int *ptr;
{ // Create a local scope
int num = 10;
ptr = &num; // 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:

Memory Management Mechanism:

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.

int *ptr = (int*)malloc(sizeof(int)); // Cast to an integer pointer


char *str = (char*)calloc(10, sizeof(char)); // Cast to a character pointer

*/

You might also like