আমি কেবল সি শিখছি এবং ভাবছিলাম যে এর মধ্যে কোনটি আমার প্রধান পদ্ধতিতে ব্যবহার করা উচিত। কোন পার্থক্য আছে? কোনটি বেশি সাধারণ?
char **argv
সমান । 2. অ্যারে পয়েন্টার নয়। char *argv[]
আমি কেবল সি শিখছি এবং ভাবছিলাম যে এর মধ্যে কোনটি আমার প্রধান পদ্ধতিতে ব্যবহার করা উচিত। কোন পার্থক্য আছে? কোনটি বেশি সাধারণ?
char **argv
সমান । 2. অ্যারে পয়েন্টার নয়। char *argv[]
উত্তর:
আপনি যেমন সি শিখছেন, আমি আপনাকে সুপারিশ করছি সাধারণ জিনিসগুলির পরিবর্তে প্রথমে অ্যারে এবং পয়েন্টারগুলির মধ্যে পার্থক্যগুলি বোঝার চেষ্টা করুন ।
প্যারামিটার এবং অ্যারেগুলির ক্ষেত্রে কয়েকটি বিভ্রান্তিকর নিয়ম রয়েছে যা চালানোর আগে পরিষ্কার হওয়া উচিত। প্রথমত, আপনি প্যারামিটার তালিকায় যা ঘোষণা করেন তা বিশেষ বিবেচিত হয়। এমন পরিস্থিতি রয়েছে যেখানে সিগুলিতে কোনও ফাংশন প্যারামিটার হিসাবে জিনিসগুলি বোঝায় না These
দ্বিতীয় সম্ভবত অবিলম্বে পরিষ্কার হয় না। আপনি স্পষ্ট হয়ে ওঠেন যখন আপনি বিবেচনা করেন যে অ্যারের মাত্রাটির আকারটি সি এর ধরণের অংশ (এবং একটি অ্যারে যার মাত্রার আকার দেওয়া হয়নি তা একটি অসম্পূর্ণ প্রকার)। সুতরাং, আপনি যদি এমন কোনও ফাংশন তৈরি করেন যা অ্যারে বাই-ভ্যালু (একটি অনুলিপি গ্রহণ করে) নেয়, তবে এটি কেবল একটি আকারের জন্যই করতে পারে! তদতিরিক্ত, অ্যারেগুলি বড় হয়ে উঠতে পারে এবং সি যথাসম্ভব দ্রুত হওয়ার চেষ্টা করে।
সিতে, এই কারণে অ্যারে-মানগুলি বিদ্যমান নেই। আপনি যদি কোনও অ্যারের মান পেতে চান তবে পরিবর্তে যা পাবেন তা হ'ল অ্যারের প্রথম উপাদানটির একটি পয়েন্টার। এবং ইতিমধ্যে ইতিমধ্যে সমাধান মিথ্যা। অবৈধ আপ-ফ্রন্টের অ্যারে প্যারামিটার আঁকার পরিবর্তে, একটি সি কম্পাইলার সংশ্লিষ্ট প্যারামিটারের প্রকারকে পয়েন্টার হিসাবে রূপান্তরিত করবে । এটি মনে রাখবেন, এটি খুব গুরুত্বপূর্ণ। প্যারামিটারটি একটি অ্যারে হবে না, তবে পরিবর্তে এটি সংশ্লিষ্ট উপাদান ধরণের পয়েন্টার হবে।
এখন, আপনি যদি অ্যারে পাস করার চেষ্টা করেন তবে এর পরিবর্তে যা পাস হবে তা অ্যারে'র প্রথম উপাদানটির পয়েন্টার।
সমাপ্তির জন্য, এবং যেহেতু আমি মনে করি এটি আপনাকে বিষয়টি আরও ভালভাবে বুঝতে সহায়তা করবে, আপনি যখন প্যারামিটার হিসাবে কোনও ফাংশন রাখার চেষ্টা করবেন তখন আসুন পরিস্থিতি কী তা দেখি। প্রকৃতপক্ষে, প্রথমে এটি কোনও ধারণা রাখবে না। একটি পরামিতি একটি ফাংশন হতে পারে? হু, আমরা অবশ্যই সেই জায়গায় একটি পরিবর্তনশীল চাই! সুতরাং কম্পাইলারটি যখন যা ঘটে তখন তা হ'ল আবার, ফাংশনটিকে একটি ফাংশন পয়েন্টারে রূপান্তরিত করতে । কোনও ক্রিয়াকলাপটি পাস করার চেষ্টা করা পরিবর্তে সংশ্লিষ্ট ফাংশনে একটি পয়েন্টার পাস করবে। সুতরাং, নিম্নলিখিতগুলি একই (অ্যারের উদাহরণের সাথে সাদৃশ্য):
void f(void g(void));
void f(void (*g)(void));
মনে রাখবেন যে আশেপাশে প্রথম বন্ধনী *g
প্রয়োজন। অন্যথায় এটি কোনও ফাংশন রিটার্নিংয়ের void*
পয়েন্টারের পরিবর্তে ফাংশন রিটার্নিং নির্দিষ্ট করে void
।
এখন, আমি শুরুতে বলেছিলাম যে অ্যারেগুলির একটি অসম্পূর্ণ প্রকার থাকতে পারে - যা আপনি এখনও কোনও আকার না দিলে ঘটে। যেহেতু আমরা ইতিমধ্যে সনাক্ত করেছি যে অ্যারে প্যারামিটারটি বিদ্যমান নেই তবে পরিবর্তে কোনও অ্যারে প্যারামিটার একটি পয়েন্টার হিসাবে রয়েছে, অ্যারের আকারটি কোনও ব্যাপার নয়। তার অর্থ, সংকলক নীচের সমস্তগুলিকে অনুবাদ করবে এবং সমস্ত একই জিনিস:
int main(int c, char **argv);
int main(int c, char *argv[]);
int main(int c, char *argv[1]);
int main(int c, char *argv[42]);
অবশ্যই, এটিতে কোনও আকার রাখতে সক্ষম হওয়ায় এটি কোনও তাত্পর্যপূর্ণ নয় এবং এটি কেবল ফেলে দেওয়া হয়েছে। সেই কারণে, C99 এই সংখ্যাগুলির জন্য একটি নতুন অর্থ নিয়ে আসে এবং বন্ধনীগুলির মধ্যে অন্যান্য জিনিসগুলি উপস্থিত হওয়ার অনুমতি দেয়:
// says: argv is a non-null pointer pointing to at least 5 char*'s
// allows CPU to pre-load some memory.
int main(int c, char *argv[static 5]);
// says: argv is a constant pointer pointing to a char*
int main(int c, char *argv[const]);
// says the same as the previous one
int main(int c, char ** const argv);
শেষ দুটি লাইন বলছে যে আপনি ফাংশনের মধ্যে "আরজিভি" পরিবর্তন করতে পারবেন না - এটি কনস্ট পয়েন্টার হয়ে গেছে। যদিও কয়েকটি সি সংকলক এই সি 99 বৈশিষ্ট্যগুলিকে সমর্থন করে। তবে এই বৈশিষ্ট্যগুলি পরিষ্কার করে দেয় যে "অ্যারে" আসলে এক নয়। এটি একটি পয়েন্টার।
মনে রাখবেন যে আমি উপরে যা বলেছি তা কেবল তখনই সত্য যখন আপনি কোনও ফাংশনের প্যারামিটার হিসাবে অ্যারে পেয়ে যাবেন। আপনি যদি স্থানীয় অ্যারে নিয়ে কাজ করেন তবে একটি অ্যারে পয়েন্টার হবে না। এটি পয়েন্টার হিসাবে আচরণ করবে , কারণ পূর্বে বর্ণিত হিসাবে একটি অ্যারে এর মান পড়লে পয়েন্টারে রূপান্তরিত হবে। তবে এটি পয়েন্টারগুলির সাথে বিভ্রান্ত হওয়া উচিত নয়।
একটি ক্লাসিক উদাহরণ নিম্নলিখিত:
char c[10];
char **c = &c; // does not work.
typedef char array[10];
array *pc = &c; // *does* work.
// same without typedef. Parens needed, because [...] has
// higher precedence than '*'. Analogous to the function example above.
char (*array)[10] = &c;
আপনি হয় ব্যবহার করতে পারেন। তারা সম্পূর্ণ সমতুল্য। দেখুন litb এর মতামত ও তার উত্তর ।
এটি কীভাবে আপনি এটি ব্যবহার করতে চান তা সত্যই নির্ভর করে (এবং আপনি যে কোনও ক্ষেত্রে ব্যবহার করতে পারেন):
// echo-with-pointer-arithmetic.c
#include <stdio.h>
int main(int argc, char **argv)
{
while (--argc > 0)
{
printf("%s ", *++argv);
}
printf("\n");
return 0;
}
// echo-without-pointer-arithmetic.c
#include <stdio.h>
int main(int argc, char *argv[])
{
int i;
for (i=1; i<argc; i++)
{
printf("%s ", argv[i]);
}
printf("\n");
return 0;
}
যার জন্য বেশি সাধারণ - তাতে কিছু আসে যায় না। আপনার কোড পড়ার যে কোনও অভিজ্ঞ সি প্রোগ্রামার উভয়ই বিনিময়যোগ্য (সঠিক অবস্থার অধীনে) দেখতে পাবে। ঠিক তেমনি একজন অভিজ্ঞ ইংরেজী স্পিকার যেমন "তারা" এবং "তারা" সমানভাবে সহজেই পড়ে।
আরও গুরুত্বপূর্ণ হ'ল আপনি সেগুলি পড়তে শিখুন এবং সেগুলি কতটা সাদৃশ্য তা স্বীকৃতি দিন। আপনি লেখার চেয়ে আরও কোড পড়বেন এবং আপনার উভয়ের সাথে সমান স্বাচ্ছন্দ্য বোধ করা দরকার।
char**
কারণ এটি আমাকে মনে করিয়ে দেয় যে এটি করার মতো সত্যিকারের অ্যারে হিসাবে আচরণ করা উচিত নয় sizeof[arr] / sizeof[*arr]
।
আপনি দুটি ফর্মের মধ্যে দুটি ব্যবহার করতে পারেন, যেমন সি অ্যারে এবং পয়েন্টারগুলি ফাংশন প্যারামিটার তালিকায় বিনিময়যোগ্য। Http://en.wikedia.org/wiki/C_( প্রোগ্রামিং_এলংয়েজ)) দেখুন: অ্যারে- পয়েন্টার_ইন্টারচেঞ্জেবিলিটি ।
আমি অন্যটির পরিবর্তে উভয়ই পদ্ধতির ব্যবহারের বিশেষ যোগ্যতা দেখছি না - আপনার কোডটির বাকী কোডের সাথে সাদৃশ্যপূর্ণ কনভেনশনটি ব্যবহার করুন।
আমি জানি এটি পুরানো, তবে আপনি যদি কেবল সি প্রোগ্রামিং ভাষা শিখতে থাকেন এবং এর সাথে বড় কিছু করেন না, কমান্ড-লাইন বিকল্পগুলি ব্যবহার করবেন না।
আপনি যদি কমান্ড লাইন যুক্তি ব্যবহার না করে থাকেন তবে তা ব্যবহার করবেন না। শুধু হিসাবে int main()
আপনি মূল ফাংশন ঘোষণা
-help
, /?
বা program name
টার্মিনাল বা কমান্ড প্রম্পটে পরবর্তী যে কোনও জিনিস ) পরিচালনা করতে চানআপনার যেটি আরও বেশি বোঝায় তা ব্যবহার করুন। অন্যথায়, int main()
সর্বোপরি ব্যবহার করুন, আপনি যদি কমান্ড-লাইন বিকল্পগুলি যুক্ত করতে চান তবে আপনি এগুলিকে পরে এডিট করতে পারবেন।