সি এর দুটি ফাংশনের মধ্যে পার্থক্য কী?
void f1(double a[]) {
//...
}
void f2(double *a) {
//...
}
যদি আমি লম্বা অ্যারেগুলিতে ফাংশনগুলি কল করতে পারি তবে এই দুটি ফাংশন কি আলাদাভাবে আচরণ করবে, তারা স্ট্যাকের উপর আরও জায়গা নেবে?
সি এর দুটি ফাংশনের মধ্যে পার্থক্য কী?
void f1(double a[]) {
//...
}
void f2(double *a) {
//...
}
যদি আমি লম্বা অ্যারেগুলিতে ফাংশনগুলি কল করতে পারি তবে এই দুটি ফাংশন কি আলাদাভাবে আচরণ করবে, তারা স্ট্যাকের উপর আরও জায়গা নেবে?
উত্তর:
প্রথমত, কিছু স্ট্যান্ডার্ডিজ :
7.7..5.৩ ফাংশন ডিক্লেয়ারার (প্রোটোটাইপ সহ)
...
'' ' টাইপের অ্যারে' 'হিসাবে একটি পরামিতি ঘোষণাকে ' 'যোগ্য পয়েন্টার টাইপ করতে' 'র সাথে সামঞ্জস্য করা হবে , যেখানে টাইপ কোয়ালিফায়ার (যদি থাকে) নির্দিষ্ট করা হয় মধ্যে[
এবং]
অ্যারের টাইপ শিক্ষাদীক্ষা করুন। যদি কীওয়ার্ডটি অ্যারের ধরণের ডাইরিভিউশন এবং এরstatic
মধ্যেও উপস্থিত হয় , তবে ফাংশনটির প্রতিটি কলের জন্য, সংশ্লিষ্ট প্রকৃত যুক্তির মান কমপক্ষে যতগুলি উপাদান নির্দিষ্ট করে ঠিক তত পরিমাণে একটি অ্যারের প্রথম উপাদানটিতে অ্যাক্সেস সরবরাহ করতে পারে অভিব্যক্তি।[
]
সুতরাং, সংক্ষেপে, কোন ফাংশন প্যারামিটার হিসেবে ঘোষণা T a[]
বা T a[N]
চিকিত্সা করা হয় যেন এটা ঘোষণা করেন T *a
।
সুতরাং, অ্যারে প্যারামিটারগুলি কেন পয়েন্টার হিসাবে ঘোষিত হয়েছে এমনভাবে তাকে চিকিত্সা করা হবে? কারণটা এখানে:
.3.৩.২.১ ল্যাভেলিউস, অ্যারে এবং ফাংশন ডিজাইনার
...
3 ব্যতীত যখন এটিsizeof
অপারেটর বা ইউনিারি&
অপারেটরের অপারেন্ড হয় বা কোনও অ্যারে শুরু করতে স্ট্রিং আক্ষরিক হয়, এমন একটি এক্সপ্রেশন যা '' টাইপের অ্যারে ' টাইপ করে 'টাইপ' 'পয়েন্টার টু টাইপ ' দিয়ে একটি এক্সপ্রেশনতে রূপান্তরিত হয় যা অ্যারে অবজেক্টের প্রাথমিক উপাদানকে নির্দেশ করে এবং লভ্যালু নয়। যদি অ্যারে অবজেক্টটিতে স্টোরেজ ক্লাসটি নিবন্ধিত থাকে তবে আচরণটি সংজ্ঞায়িত।
নিম্নলিখিত কোড দেওয়া:
int main(void)
{
int arr[10];
foo(arr);
...
}
কলটিতে foo
অ্যারে এক্সপ্রেশনটি arr
কোনও sizeof
বা একটির অপরেন্দ্র নয় &
, সুতরাং এর প্রকারটি স্পষ্টভাবে 6.2.3.1/3 অনুযায়ী "10-উপাদান অ্যারে int
" থেকে "পয়েন্টারে int
" রূপান্তরিত হয়। সুতরাং, foo
অ্যারের মানের পরিবর্তে একটি পয়েন্টার মান পাবেন।
6.7.5.3/7 কারণে আপনি লিখতে পারেন foo
যেমন
void foo(int a[]) // or int a[10]
{
...
}
তবে এটি ব্যাখ্যা করা হবে
void foo(int *a)
{
...
}
সুতরাং, দুটি রূপ অভিন্ন।
6.7.5.3/7 এ শেষ বাক্যটি C99 এর সাথে প্রবর্তিত হয়েছিল এবং মূলত এর অর্থ হল যে আপনার যদি পরামিতি ঘোষণার মতো থাকে
void foo(int a[static 10])
{
...
}
সাথে সম্পর্কিত প্রকৃত প্যারামিটারটি a
অবশ্যই কমপক্ষে 10 টি উপাদান সহ একটি অ্যারে হতে হবে ।
পার্থক্যটি নিখুঁত বাক্য গঠনমূলক। সি-তে, যখন অ্যারে চিহ্নিতকরণটি কোনও ফাংশন প্যারামিটারের জন্য ব্যবহৃত হয়, এটি স্বয়ংক্রিয়ভাবে পয়েন্টার ঘোষণায় রূপান্তরিত হয়।
না, তাদের মধ্যে কোনও পার্থক্য নেই। পরীক্ষা করতে আমি এই সি কোডটি ডেভ সি ++ (মিংডাব্লু) সংকলকটিতে লিখেছি:
#include <stdio.h>
void function(int* array) {
int a =5;
}
void main() {
int array[]={2,4};
function(array);
getch();
}
আমি যখন আইডিএতে বাইনারি ফাইলের উভয় কলিং সংস্করণগুলির .exe এ মূল ফাংশনটি বিচ্ছিন্ন করতে পারি তখন আমি নীচের মতো ঠিক একই সমাবেশ কোড পাই:
push ebp
mov ebp, esp
sub esp, 18h
and esp, 0FFFFFFF0h
mov eax, 0
add eax, 0Fh
add eax, 0Fh
shr eax, 4
shl eax, 4
mov [ebp+var_C], eax
mov eax, [ebp+var_C]
call sub_401730
call sub_4013D0
mov [ebp+var_8], 2
mov [ebp+var_4], 4
lea eax, [ebp+var_8]
mov [esp+18h+var_18], eax
call sub_401290
call _getch
leave
retn
সুতরাং এই কলটির দুটি সংস্করণের মধ্যে কোনও পার্থক্য নেই, কমপক্ষে সংকলক তাদের সমানভাবে হুমকি দেয়।