সূচিপত্র

এই পর্বের শুরুতেই আমরা আলোচনা করবো অ্যারের সীমাবদ্ধতা নিয়ে। আমরা দেখেছি অ্যারে ডিক্লেয়ার করার সময় আমাদের অনুমানের উপর বলে দিতে হয় সর্বোচ্চ কতটি উপাদান আমাদের লাগতে পারে। বেশিরভাগ ক্ষেত্রে ততটি উপাদান আমাদের লাগে না, এবং অপচয় হয় মেমরির। আবার অ্যারের ধারণক্ষমতা সীমাবদ্ধ, এবং সেটাও খুব বেশি না। লোকাল স্পেসে ডিক্লেয়ার করা একটি অ্যারের সর্বোচ্চ ধারনক্ষমতা প্রায় ৩২৭০০ টি ইন্টিজার। গ্লোবাল স্পেসের ক্ষেত্রে সেটা এক লক্ষের কিছু বেশি।

কিন্তু আমাদের তো এর চেয়েও বেশি ইন্টিজারের প্রয়োজন হতে পারে! এধরণের ক্ষেত্রেই আমাদের প্রয়োজন পড়ে ডাইনামিকভাবে মেমরি এলোকেট করার। এর সুবিধা হল এর মাধ্যমে আমরা কম্পাইল টাইমে নতুন মেমরি নিতে পারি। আবার কাজ শেষে সেই মেমরি মুক্ত (ফ্রী বা রিলিজ) করে দিতে পারি! মূলত stdlib.h হেডার ফাইলের ৪ টি লাইব্রেরী ফাংশন এজন্য আমাদের লাগবে।

  • malloc()
  • calloc()
  • free()
  • realloc()

malloc()

malloc-এর পূর্ণ রূপ হল memory allocation। নাম থেকেই বুঝা যায় মেমরি নেওয়ার জন্য এই ফাংশনটা ব্যবহার করা হবে! এটি ব্যবহার করার নিয়মটা নিচের মতঃ

#include <stdio.h>
#include <stdlib.h>
int main() {
    int *ptr;
    ptr = (int*) malloc(sizeof(int));
    printf("%d\n", ptr);
    return 0;
}

রান করলে দেখবা একেকবার একেকধরণের মান আসছে। কারণ মেমরি এলোকেট করা হচ্ছে কম্পাইল করার সময়! আর (int*)-এর ব্যাপারটা নতুন। এটা হচ্ছে টাইপ কাস্টিং। এ ব্যাপারে পরে আরও বিস্তারিত জানতে পারবে। আপাতত শুধু দেখে রাখ! :p

আবার আমরা নিচের কোডটা লিখলে integer-এর সাইজের ১০০ গুণ মেমরি এলোকেট হয়ে যাবে!

#include <stdio.h>
#include <stdlib.h>
int main() {
    int *ptr;
    ptr = (int*) malloc(100*sizeof(int));
    printf("%d\n", ptr);
    
    return 0;
}

এখন ইন্টিজারের সাইজের ১০০ গুণ মেমরি এলোকেট হবে এবং পয়েন্টারটি এই মেমরির শুরুর বাইটটা নির্দেশ করবে।

calloc()

calloc-এর পূর্ণ রূপ হল contiguous allocation, অর্থাৎ পাশাপাশি! malloc শুধু মেমরির একটা ব্লক এলোকেট করে, calloc মেমরির কিছু ব্লক (অবশ্যই পাশাপাশি) একসাথে এলোকেট করে। অর্থাৎ অনেকটা অ্যারের মত!

এটি ব্যবহার করার নিয়ম হলঃ

#include <stdio.h>
#include <stdlib.h>
int main() {
    int *ptr;
    ptr = (int*) calloc(25, sizeof(int));
    return 0;
}

এখন যা হবে, তা হল ইন্টিজারের সাইজ বিশিষ্ট পাশাপাশি ২৫ টি মেমরি ব্লক এলোকেট হবে এবং পয়েন্টারটি এদের প্রথমটির শুরুর বাইটটি নির্দেশ করবে।

free()

আমরা মেমরি ব্যবহার করা শেষে সেটি মুক্ত করে দিব free ব্যবহার করে। কারণ না হলে সেই মেমরি এলোকেটেড অবস্থাতেই থেকে যাবে। এটি ব্যবহার করতে হয় নিচের নিয়মেঃ

#include <stdio.h>
#include <stdlib.h>
int main() {
    int *ptr;
    ptr = (int*) malloc(sizeof(int));
    printf("%d\n", ptr);
    free(ptr);
    return 0;
}

realloc()

ধর আমরা একবার মেমরি এলোকেট করলাম। এখন কোনো কারণে আমাদের এর চেয়েও বেশি মেমরি প্রয়োজন হচ্ছে (কিংবা, আরও কম লাগছে)। তখন আমরা আমাদের মেমরির সাইজটা পরিবর্তন করতে পারি realloc() ব্যবহার করে।

#include <stdio.h>
#include <stdlib.h>
int main() {
    int *ptr, *ptr2;
    ptr = (int*) calloc(25*sizeof(int));
    ptr2 = realloc(ptr, 100*sizeof(int)) 
    return 0;
}

এখানে ptr-কে যে মেমরির শুরুর অ্যাড্রেস দেওয়া হয়েছিল সেটারই পরিবর্তন করে নতুন মেমরি এলোকেট করা হবে এবং সেই মেমরির শুরুটা ptr2-কে দেওয়া হবে!

________________________________________________________________

আমরা এবার malloc() ব্যবহার করে অ্যারের কাজ করবো। আমাদের কাজ হবে n সংখ্যক ইন্টিজার ইনপুট নিয়ে তাদের যোগফল প্রিন্ট করা।

#include <stdio.h>
#include <stdlib.h>
int main(){
    int n,i,*ptr,sum=0;
    printf("Enter number of elements: ");
    scanf("%d",&n);

    ptr=(int*)malloc(n*sizeof(int));  //memory allocated using malloc

    if(ptr==NULL)
        printf("Oops, memory was not allocated.\n"); // jodi kono karone memory allocate korte jhamela hoi

    printf("Enter the elements: ");

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

    printf("Sum = %d\n",sum);
    free(ptr);

    return 0;
}

একই কাজ আমরা calloc() ব্যবহার করেও করতে পারতামঃ

#include <stdio.h>
#include <stdlib.h>
int main(){
    int n,i,*ptr,sum=0;
    printf("Enter number of elements: ");
    scanf("%d",&n);

    ptr=(int*)calloc(n, sizeof(int));  //memory allocated using malloc

    if(ptr==NULL)
        printf("Oops, memory was not allocated.\n"); // jodi kono karone memory allocate korte jhamela hoi

    printf("Enter the elements: ");

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

    printf("Sum = %d\n",sum);
    free(ptr);

    return 0;
}

শুধু একটি লাইন বদলে দিয়েছি! 😉

এবার ধরা যাক, n সংখ্যক ইন্টিজার দেওয়ার পর ইউজার জানালো যে, সে এবার k সংখ্যক ইন্টিজারের যোগফল জানতে চায়। এক্ষেত্রে আমরা ব্যবহার করবো realloc!

#include <stdio.h>
#include <stdlib.h>
int main(){
    int n,i,*ptr,sum=0;
    printf("Enter number of elements: ");
    scanf("%d",&n);

    ptr=(int*)malloc(n* sizeof(int));  //memory allocated using malloc

    if(ptr==NULL)
        printf("Oops, memory was not allocated.\n"); // jodi kono karone memory allocate korte jhamela hoi

    printf("Enter the elements: ");

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

    printf("Sum = %d\n",sum);
    int k, *ptr2;
    printf("Enter the new number of elements: ");
    scanf("%d", &k);
    ptr2 = realloc(ptr, k*sizeof(int));
    if(ptr2==NULL)
        printf("Oops, memory was not allocated.\n"); // jodi kono karone memory allocate korte jhamela hoi

    printf("Enter the elements: ");
    sum = 0;
    for(i=0;i<k;++i) {
        scanf("%d",ptr+i);
        sum+=*(ptr+i);
    }
    printf("New sum = %d\n", sum);
    free(ptr);

    return 0;
}

খেয়াল কর, আমরা সব ক্ষেত্রেই কাজ শেষে মেমরি ফ্রি করে দিচ্ছি। এটা করা হচ্ছে কারণ malloc, calloc দিয়ে যে মেমরিটা এলোকেট করা হয়, সেটা নিজে নিজে মুক্ত হয়ে যায় না। বরং প্রোগ্রাম যতক্ষণ চলে ততক্ষণই এলোকেটেড থাকে। শুধু শুধু মেমরিটা ফেলে রাখার তো কোনো মানে হয় না!

Muntasir Wahed

Muntasir Wahed

System Administrator at স্বশিক্ষা.com
Jack of all trades, master of none.
Muntasir Wahed
Muntasir Wahed