আপনি আপনার পোস্টে যা বলছেন তা একেবারে সঠিক। আমি বলব যে প্রতিটি সি বিকাশকারী ঠিক একই আবিষ্কার এবং ঠিক একই সিদ্ধান্তে আসে যখন তারা সি ভাষার সাথে নির্দিষ্ট দক্ষতার পর্যায়ে পৌঁছায়।
আপনার অ্যাপ্লিকেশন ক্ষেত্রের নির্দিষ্টকরণ নির্দিষ্ট নির্দিষ্ট আকারের অ্যারের জন্য ডাকে (অ্যারের আকারটি একটি সংকলন-সময় ধ্রুবক), পয়েন্টার-থেকে-অ্যারে প্যারামিটার ব্যবহার করে কোনও ফাংশনে এই জাতীয় অ্যারে পাস করার একমাত্র সঠিক উপায় is
void foo(char (*p)[10]);
(সি ++ ভাষায় এটিও রেফারেন্স সহ করা হয়
void foo(char (&p)[10]);
)।
এটি ভাষা-স্তরের প্রকারের চেকিং সক্ষম করবে, যা নিশ্চিত করবে যে ঠিক সঠিক আকারের অ্যারেটি আর্গুমেন্ট হিসাবে সরবরাহ করা হয়েছে। প্রকৃতপক্ষে, অনেক ক্ষেত্রে লোকেরা এই কৌশলটি স্পষ্টভাবেই ব্যবহার করে, এমনকি এটি উপলব্ধি না করেই, টাইপডেফ নামের পিছনে অ্যারের প্রকারটি লুকিয়ে রাখে
typedef int Vector3d[3];
void transform(Vector3d *vector);
/* equivalent to `void transform(int (*vector)[3])` */
...
Vector3d vec;
...
transform(&vec);
অতিরিক্ত নোট করুন যে উপরের কোড সম্পর্কিত সঙ্গে পরিবর্তিত হয় Vector3d
একটি অ্যারে অথবা একটি হচ্ছে টাইপ struct
। আপনি Vector3d
যে কোনও সময় সংজ্ঞাটি আরে থেকে struct
পিছনে ফিরে যেতে পারেন এবং আপনাকে ফাংশন ঘোষণাটি পরিবর্তন করতে হবে না decla উভয় ক্ষেত্রেই ফাংশনগুলি "রেফারেন্স দ্বারা" একটি সামগ্রিক বস্তু গ্রহণ করবে (এর ব্যতিক্রম আছে তবে এই আলোচনার প্রসঙ্গে এটি সত্য)।
তবে অ্যারে পাস করার এই পদ্ধতিটি আপনি খুব বেশি স্পষ্টভাবে ব্যবহার করতে পারবেন না, কারণ খুব বেশি লোক একটি বরং সংশ্লেষিত বাক্য গঠন দ্বারা বিভ্রান্ত হয়ে পড়ে এবং সি ভাষার এই জাতীয় বৈশিষ্ট্যগুলি সঠিকভাবে ব্যবহার করার জন্য যথেষ্ট স্বাচ্ছন্দ্য বোধ করে না। এই কারণে, গড়পড়তা বাস্তব জীবনে, প্রথম উপাদানটিতে পয়েন্টার হিসাবে একটি অ্যারে পাস করা আরও জনপ্রিয় পদ্ধতির। এটি কেবল "সরল" দেখায়।
কিন্তু বাস্তবে, অ্যারে পাস করার জন্য পয়েন্টারটি প্রথম উপাদানটিতে ব্যবহার করা একটি খুব কুলুঙ্গিক কৌশল, একটি কৌশল, যা খুব নির্দিষ্ট উদ্দেশ্যে কাজ করে: এর এক এবং একমাত্র উদ্দেশ্য হ'ল বিভিন্ন আকারের অ্যারেগুলি পাস করা (যেমন রান-টাইম আকার) । যদি আপনার সত্যিই রান-টাইম আকারের অ্যারেগুলি প্রক্রিয়া করতে সক্ষম হতে হয়, তবে এ জাতীয় অ্যারেটি পাশ করার যথাযথ উপায়টি অতিরিক্ত পরামিতি দ্বারা সরবরাহিত কংক্রিটের আকারের সাথে তার প্রথম উপাদানটির পয়েন্টার দ্বারা হয় is
void foo(char p[], unsigned plen);
আসলে, অনেক ক্ষেত্রে রান-টাইম আকারের অ্যারেগুলি প্রক্রিয়া করতে সক্ষম হওয়া খুব দরকারী, যা পদ্ধতির জনপ্রিয়তায়ও অবদান রাখে। অনেক সি বিকাশকারী কখনও স্থির আকারের অ্যারে প্রক্রিয়া করার প্রয়োজনের মুখোমুখি হন না (বা কখনও চিনতে পারেন না), ফলে সঠিক স্থির-আকারের কৌশলটি থেকে গাফেল থাকেন।
তবুও, যদি অ্যারের আকারটি স্থির থাকে তবে এটি কোনও উপাদানকে নির্দেশক হিসাবে প্রেরণ করে
void foo(char p[])
একটি বড় কৌশল-স্তরের ত্রুটি, যা দুর্ভাগ্যক্রমে আজকের দিনে বরং এটি ব্যাপকভাবে ছড়িয়ে পড়ে। পয়েন্টার-টু-অ্যারে কৌশল এমন ক্ষেত্রে একটি আরও ভাল পদ্ধতির।
স্থির আকারের অ্যারে পাসিং কৌশলটি গ্রহণে বাধা হয়ে উঠতে পারে এমন আরও একটি কারণ হ'ল গতিশীলভাবে বরাদ্দ হওয়া অ্যারেগুলি টাইপ করার ক্ষেত্রে নিষ্পাপ পদ্ধতির আধিপত্য। উদাহরণস্বরূপ, যদি প্রোগ্রামটি নির্দিষ্ট ধরণের অ্যারেগুলির জন্য কল করে char[10]
(আপনার উদাহরণ হিসাবে), একজন গড় বিকাশকারী malloc
যেমন অ্যারেগুলিকে
char *p = malloc(10 * sizeof *p);
এই অ্যারেটি হিসাবে ঘোষিত কোনও ফাংশনে পাস করা যাবে না
void foo(char (*p)[10]);
যা গড় বিকাশকারীকে বিভ্রান্ত করে এবং এটিকে আরও চিন্তাভাবনা না করে স্থির আকারের প্যারামিটার ঘোষণাটি ত্যাগ করে। বাস্তবে যদিও, সমস্যার মূলটি নিখুঁত malloc
পদ্ধতির মধ্যে রয়েছে। malloc
উপরে দেখানো বিন্যাস রান-টাইম আকারের অ্যারে জন্য সংরক্ষিত করা উচিত। যদি অ্যারের ধরণের সংকলন-সময় আকার থাকে, তবে এর থেকে আরও ভাল উপায় malloc
নিম্নলিখিত হিসাবে দেখাবে
char (*p)[10] = malloc(sizeof *p);
এটি অবশ্যই উপরের ঘোষণায় সহজেই পাস করা যেতে পারে foo
foo(p);
এবং সংকলক সঠিক টাইপ চেকিং সঞ্চালন করবে। তবে আবার, এটি অপ্রস্তুত সি বিকাশকারীকে অত্যধিক বিভ্রান্ত করছে, এ কারণেই আপনি এটি প্রায়শই "সাধারণ" দৈনিক গড় কোডে দেখতে পাবেন না।
10
হবে না, সুযোগের কোনও পরিবর্তনশীল দ্বারা প্রতিস্থাপন করা যেতে পারে