অ্যারে এবং ফাংশনগুলির সাথে কাজ করার সময় একটি প্যাটার্ন রয়েছে; এটি প্রথমে দেখতে কিছুটা শক্ত।
অ্যারেগুলির সাথে কাজ করার সময়, নিম্নলিখিতগুলি মনে রাখার জন্য এটি দরকারী: যখন একটি অ্যারে এক্সপ্রেশন বেশিরভাগ প্রসঙ্গে উপস্থিত হয়, তখন এক্সপ্রেশনটির প্রকার স্পষ্টভাবে "টি এর এন-এলিমেন্ট অ্যারে" থেকে "পয়েন্টার থেকে টি" তে রূপান্তরিত হয় এবং এর মান সেট করা হয় অ্যারেতে প্রথম উপাদানটি নির্দেশ করতে point এই নিয়মের ব্যতিক্রমগুলি হ'ল যখন অ্যারে এক্সপ্রেশনটি অপারেটরগুলির &
বা sizeof
অপারেটরগুলির উপস্থিতি হিসাবে উপস্থিত হয় , বা যখন এটি কোনও স্ট্রিং আক্ষরিক হয় তখন একটি ঘোষণায় প্রারম্ভিক হিসাবে ব্যবহৃত হয়।
সুতরাং, আপনি যখন একটি অ্যারের এক্সপ্রেশন সহ কোনও ফাংশনটিকে আর্গুমেন্ট হিসাবে কল করবেন তখন ফাংশনটি বিন্যাস নয়, অ্যারে নয় একটি পয়েন্টার গ্রহণ করবে:
int arr[10];
...
foo(arr);
...
void foo(int *arr) { ... }
এই কারণেই আপনি "% s" এর সাথে যুক্ত যুক্তিগুলির জন্য অপারেটরটি ব্যবহার করবেন না :&
scanf()
char str[STRING_LENGTH];
...
scanf("%s", str);
অন্তর্নিহিত রূপান্তর কারণে, অ্যারের শুরুতে নির্দেশ করে এমন scanf()
একটি char *
মান গ্রহণ করে str
। এটি আর্গুমেন্ট হিসাবে অ্যারে এক্সপ্রেশন সহ যে কোনও ক্রিয়াকলাপের ক্ষেত্রে সত্য (এটি কোনও str*
ফাংশন *scanf
এবং *printf
ফাংশন ইত্যাদির সম্পর্কে) সত্য বলে ধরে রাখে ।
অনুশীলনে, আপনি সম্ভবত কখনও কখনও &
অপারেটরটি ব্যবহার করে অ্যারে এক্সপ্রেশন সহ কোনও ফাংশন কল করবেন না:
int arr[N];
...
foo(&arr);
void foo(int (*p)[N]) {...}
এই জাতীয় কোড খুব সাধারণ নয়; আপনাকে ফাংশন ঘোষণায় অ্যারেটির আকার জানতে হবে এবং ফাংশনটি নির্দিষ্ট আকারের অ্যারেগুলিতে পয়েন্টার দিয়ে কাজ করে (টি-এর একটি 10-এলিমেন্ট অ্যারের একটি পয়েন্টার 11-এলিমেন্ট অ্যারের পয়েন্টারের চেয়ে আলাদা ধরণের হয় টি এর)।
যখন একটি অ্যারের এক্সপ্রেশন &
অপারেটরের কাছে অপরেন্ড হিসাবে উপস্থিত হয় , তখন ফলাফলটির এক্সপ্রেশনটি টাইপ হয় "টি এর এন-এলিমেন্ট অ্যারে থেকে পয়েন্টার", বা T (*)[N]
, যা পয়েন্টার ( T *[N]
) এর অ্যারে থেকে আলাদা এবং বেস টাইপের পয়েন্টার ( T *
)।
ফাংশন এবং পয়েন্টারগুলির সাথে কাজ করার সময়, মনে রাখার নিয়মটি হ'ল: আপনি যদি কোনও যুক্তির মান পরিবর্তন করতে চান এবং কলিং কোডটিতে এটি প্রতিবিম্বিত করতে চান তবে আপনাকে যে জিনিসটি সংশোধন করতে চান তার জন্য আপনাকে অবশ্যই একটি পয়েন্টার দিতে হবে। আবার অ্যারেগুলি কিছুটা বানরের রেঞ্চটি কাজে ফেলে দেয় তবে আমরা প্রথমে সাধারণ ক্ষেত্রে মোকাবিলা করব।
মনে রাখবেন যে সি সমস্ত ফাংশন আর্গুমেন্টকে মান দ্বারা পাস করে; আনুষ্ঠানিক প্যারামিটার প্রকৃত প্যারামিটারে মানটির একটি অনুলিপি গ্রহণ করে এবং আনুষ্ঠানিক প্যারামিটারে কোনও পরিবর্তন প্রকৃত প্যারামিটারে প্রতিফলিত হয় না। সাধারণ উদাহরণটি হল অদলবদল কার্য:
void swap(int x, int y) { int tmp = x; x = y; y = tmp; }
...
int a = 1, b = 2;
printf("before swap: a = %d, b = %d\n", a, b);
swap(a, b);
printf("after swap: a = %d, b = %d\n", a, b);
আপনি নিম্নলিখিত আউটপুট পাবেন:
অদলবদলের আগে: a = 1, খ = 2
অদলবদলের পরে: a = 1, খ = 2
আনুষ্ঠানিক প্যারামিটারগুলি x
এবং y
এর থেকে পৃথক বস্তু a
এবং b
তাই পরিবর্তিত হয় x
এবং এতে y
প্রতিফলিত হয় না a
এবং b
। যেহেতু আমরা মান পরিবর্তন করতে চান a
এবং b
আমরা পাস করতে হবে পয়েন্টার swap 'র ফাংশন তাদের:
void swap(int *x, int *y) {int tmp = *x; *x = *y; *y = tmp; }
...
int a = 1, b = 2;
printf("before swap: a = %d, b = %d\n", a, b);
swap(&a, &b);
printf("after swap: a = %d, b = %d\n", a, b);
এখন আপনার আউটপুট হবে
অদলবদলের আগে: a = 1, খ = 2
অদলবদলের পরে: a = 2, খ = 1
উল্লেখ্য, swap 'র ফাংশন, আমরা মান পরিবর্তন করবেন না x
এবং y
, কিন্তু কি মান x
এবং y
বিন্দু থেকে । লেখালেখি লেখার *x
চেয়ে আলাদা x
; আমরা মানটি x
নিজের মধ্যে আপডেট করছি না , আমরা সেই অবস্থান থেকে একটি অবস্থান পাই x
এবং সেই মানটির আপডেট করি।
এটি সমানভাবে সত্য যদি আমরা কোনও পয়েন্টারের মান পরিবর্তন করতে চাই; যদি আমরা লিখি
int myFopen(FILE *stream) {stream = fopen("myfile.dat", "r"); }
...
FILE *in;
myFopen(in);
তারপরে আমরা ইনপুট প্যারামিটারের মানটি সংশোধন করছি stream
, কোনটি stream
নির্দেশ করে না তাই পরিবর্তনের stream
মানটির উপর কোনও প্রভাব পড়ে না in
; এটি কাজ করার জন্য, আমাদের অবশ্যই পয়েন্টারে একটি পয়েন্টারে যেতে হবে:
int myFopen(FILE **stream) {*stream = fopen("myFile.dat", "r"); }
...
FILE *in;
myFopen(&in);
আবার অ্যারেগুলি কিছুটা বানরের রেঞ্চকে কাজগুলিতে ফেলে দেয়। আপনি যখন কোনও ফাংশনে অ্যারে এক্সপ্রেশনটি পাস করেন তখন ফাংশনটি কীটি পায় তা পয়েন্টার। অ্যারে সাবস্ক্রিপশন কীভাবে সংজ্ঞায়িত করা হয়েছে তার কারণে আপনি পয়েন্টারে একইভাবে সাবস্ক্রিপ্ট অপারেটরটি অ্যারেতে ব্যবহার করতে পারেন:
int arr[N];
init(arr, N);
...
void init(int *arr, int N) {size_t i; for (i = 0; i < N; i++) arr[i] = i*i;}
নোট করুন যে অ্যারে অবজেক্টগুলি বরাদ্দ করা যাবে না; অর্থাত্, আপনি এর মতো কিছু করতে পারবেন না
int a[10], b[10];
...
a = b;
সুতরাং আপনি যখন অ্যারেগুলিতে পয়েন্টারগুলি ব্যবহার করছেন তখন সাবধানতা অবলম্বন করতে চান; কিছুটা এইরকম
void (int (*foo)[N])
{
...
*foo = ...;
}
কাজ করবে না