আরগাক কেন ধ্রুবক নয়?


104
int main( const int argc , const char[] const argv)

কার্যকর সি ++ আইটেম # 3 হিসাবে "যখনই সম্ভব কনট ব্যবহার করুন" বলে আমি ভাবতে শুরু করি "কেন এই 'ধ্রুবক' পরামিতিগুলি তৈরি করবেন না const?"।

কোনও argcপ্রোগ্রামে এর মানটি সংশোধন করা হয়েছে এমন কোনও দৃশ্য আছে কি ?


38
আপনি argcহিসাবে ঘোষণা করতে নির্দ্বিধায় const
অলিভার চার্লসওয়ার্থ

14
আমি অনেকগুলি প্রোডাকশন মানের কোড দেখেছি যা এটি করে:--argc
অনিকেত ইনজ

2
আমি ভাবছিলাম এটি সি উত্তরাধিকারের সাথে করার আছে, তবে কীভাবে তা জানতাম না।
লুইস মাচুকা

13
আমি সন্দেহ করি যে "যখনই সম্ভব সম্ভব কনট ব্যবহার করুন" রেফারেন্স দ্বারা পাস হওয়া জিনিসগুলিকে বোঝায়, যেখানে ফাংশনটির মধ্যে কোনও পরিবর্তন যখন ফাংশনটি শেষ হয়ে যায় তখন থেকেই যায়। এটি পূর্ণসংখ্যার মতো মান দ্বারা পাস হওয়া জিনিসগুলির সাথে সত্য নয়, সুতরাং এটি তৈরি করে লাভ করার কিছুই নেই const; প্রকৃতপক্ষে, argcএকটি const intউপায় হিসাবে পাস করার পরে আপনি argcফাংশনটির ভিতরে কোনও কাউন্টার হিসাবে ব্যবহার করতে পারবেন না ।
স্টিভ মেল্নিকফ

4
@ স্টিভমেল্নিকফ: আমি একমত নই যে constপাস-বাই-ভ্যালু প্যারামিটার তৈরি করে লাভ করার কিছুই নেই । যেমন দেখুন stackoverflow.com/a/8714278/277304 এবং stackoverflow.com/a/117557/277304
leonbloy

উত্তর:


114

এই ক্ষেত্রে, ইতিহাস একটি ফ্যাক্টর। সি এই ইনপুটগুলিকে "ধ্রুবক নয়" হিসাবে সংজ্ঞায়িত করে এবং বিদ্যমান সি কোডের (একটি ভাল অংশ) সাথে সামঞ্জস্যতা সি ++ এর প্রাথমিক লক্ষ্য ছিল।

কিছু ইউনিক্স এপিআই, যেমন getopt, আসলে ম্যানিপুলেট করে argv[], তাই এটি constসেই কারণে তৈরিও করা যায় না।

(একদিকে: মজার বিষয়, যদিও getoptএর প্রোটোটাইপ argv[]থেকে getoptবোঝানো হয়েছে যে এটি পরিবর্তিত হবে না তবে নির্দেশিত স্ট্রিংগুলিকে সংশোধন করতে পারে, লিনাক্স ম্যান পৃষ্ঠাটি ইঙ্গিত দেয় যে তার যুক্তিগুলি অনুমোদন দেয় , এবং দেখা যাচ্ছে তারা দুষ্টু হচ্ছে । মুক্ত পৃষ্ঠাতে ম্যান পৃষ্ঠাটি গোষ্ঠী এই অনুক্রমের কথা উল্লেখ করে না))

ফেলে constউপর argcএবং argvঅনেক কিনতে হবে না, এবং এটি প্রোগ্রামিং যেমন চর্চা, কিছু পুরানো-স্কুল বাতিল হবে:

// print out all the arguments:
while (--argc)
    std::cout << *++argv << std::endl;

আমি সি তে এই জাতীয় প্রোগ্রাম লিখেছি এবং আমি জানি আমি একা নই। আমি কোথাও থেকে উদাহরণটি অনুলিপি করেছি ।


1
-১ রে "কিছু ইউনিক্স এপিআই, যেমন গোটোপ্ট, আসলে আরগভি হেরফের করে [], তাই এ কারণেই এটি স্থির করা যায় না" " এক অবাধে একটি টপ লেভেল যোগ করতে পারেন constথেকে argvকোন সি ফাংশন কি করতে পারি প্রভাবিত না করেই। এছাড়াও, getoptহিসাবে ঘোষণা করা হয় int getopt(int argc, char * const argv[], const char *optstring);। এবং এখানে constশীর্ষ স্তরের নয়, তবে পয়েন্টারগুলি হ'ল ঘোষণা করেছে constযে তাদের সংশোধন না করার প্রতিশ্রুতি (যদিও তারা যে স্ট্রিংগুলিকে নির্দেশ করে তারা সম্ভবত সংশোধনযোগ্য হতে পারে)।
চিয়ার্স এবং এইচটিএইচ - আলফ

@ Cheersandhth.-আলফ: getopt permutesargv[] ডিফল্টরূপে অ্যারের কিন্তু স্ট্রিং পরিবর্তন নেই। ( ক্রমিউট শব্দটি সরাসরি ম্যান পৃষ্ঠা থেকে এসেছে)) এর অর্থ argvহ'ল অ্যারে নিজেই constএটির দ্বারা নির্দেশিত স্ট্রিংগুলি হলেও নয় । argv[]অ্যারে হস্তক্ষেপ না করে কীভাবে অনুমতি দিচ্ছে ?
জো জেড

1
আমি দুঃখিত, আমি যে দস্তাবেজগুলিতে দেখেছি তা বেমানান: স্বাক্ষরটি এ জাতীয় অনুমোদনের অনুমতি দেয় না। উদাহরণ দেখুন । তবে, নিম্নলিখিত পাঠ্যটি বলে যে এটি অনুমতি দেয়। সুতরাং, আমি ডাউনভোটটি সরিয়ে দিচ্ছি।
চিয়ার্স এবং এইচটিএইচ - Alf

1
এটি হল, আপনাকে "আনলক" করতে কিছু সম্পাদনা করতে হবে যাতে আমি ডাউনভোটটি সরিয়ে ফেলতে পারি। এবং না, আপনি প্রোটোটাইপটি ভুল বুঝছেন। আমি যে উদাহরণ সরবরাহ করেছি এবং সংকলন ত্রুটিটি দেখুন, "কেবলমাত্র পঠনযোগ্য অবস্থানের অ্যাসাইনমেন্ট"।
চিয়ার্স এবং এইচটিএইচ - Alf

1
@ চিয়ারসান্থথ-আলফ: এটি আকর্ষণীয় ... আমি শিরোনামের প্রোটোটাইপটি দেখলাম এবং এটি char* const* ___argvসেখানে রয়েছে তবে ইন্টারফেসটি আসলে মেনে চলে const char **। এমন বিভ্রান্তি আমি প্রভুর নজির []এবং *শ্রদ্ধার সাথে গুলিয়ে ফেলেছিলাম const। আমার ক্ষমা।
জো জেড

36

সি স্ট্যান্ডার্ড (আইএসও / আইইসি 9899: 2011) বলেছেন:

5.1.2.2.1 প্রোগ্রাম সূচনা

¶1 প্রোগ্রাম স্টার্টআপে ডাকা ফাংশনটির নাম দেওয়া হয়েছে main। বাস্তবায়ন এই ফাংশনের জন্য কোনও প্রোটোটাইপ ঘোষণা করে না। এটি কোনও রিটার্ন টাইপ ইন্ট এবং কোনও পরামিতি ছাড়াই সংজ্ঞায়িত করা হবে:

int main(void) { /* ... */ }

বা দুটি প্যারামিটার সহ (এখানে হিসাবে উল্লেখ করা হয় argcএবং argv, যদিও কোনও নাম ব্যবহার করা যেতে পারে, কারণ তারা যে ফাংশনটিতে তারা ঘোষিত হয়েছে তাতে স্থানীয় হয়):

int main(int argc, char *argv[]) { /* ... */ }

বা সমমানের; 10) বা অন্য কোনও বাস্তবায়ন-সংজ্ঞায়িত পদ্ধতিতে।

¶2 যদি এগুলি ঘোষণা করা হয় তবে mainফাংশনের পরামিতিগুলি নিম্নলিখিত সীমাবদ্ধতাগুলি মেনে চলবে:

  • এর মান argcননীজিটিভ হবে।
  • argv[argc] একটি নাল পয়েন্টার হতে হবে।
  • মানটি যদি argcশূন্যের চেয়ে বেশি argv[0]হয় তবে argv[argc-1]অন্তর্ভুক্তির মাধ্যমে অ্যারে সদস্যগুলির মধ্যে স্ট্রিংয়ের পয়েন্টার থাকতে হবে যা প্রোগ্রাম শুরু হওয়ার আগে হোস্ট পরিবেশ দ্বারা বাস্তবায়ন-সংজ্ঞায়িত মান দেওয়া হয়। উদ্দেশ্যটি হ'ল পরিবেশযুক্ত পরিবেশে অন্য কোথাও থেকে প্রোগ্রাম শুরু হওয়ার আগে নির্ধারিত প্রোগ্রামের তথ্য সরবরাহ করা। হোস্ট এনভায়রনমেন্ট যদি বড় হাতের এবং ছোট হাতের অক্ষরে অক্ষর দিয়ে স্ট্রিং সরবরাহ করতে সক্ষম না হয় তবে বাস্তবায়ন নিশ্চিত করবে যে স্ট্রিংগুলি ছোট হাতের মধ্যে প্রাপ্ত হয়েছে।
  • মানটি যদি argcশূন্যের চেয়ে বেশি হয় তবে নির্দেশিত স্ট্রিং argv[0] প্রোগ্রামটির নাম উপস্থাপন করে; argv[0][0]হোস্ট পরিবেশ থেকে প্রোগ্রামের নামটি উপলব্ধ না হলে নাল অক্ষর হবে shall তাহলে এর মান argcএক চেয়ে অনেক বেশী, স্ট্রিং দ্বারা প্রতি ইঙ্গিত argv[1]মাধ্যমে argv[argc-1] প্রোগ্রাম পরামিতি প্রতিনিধিত্ব করে।
  • অ্যারে দ্বারা নির্দেশিত প্যারামিটারগুলি argcএবং argvস্ট্রিংগুলি argvপ্রোগ্রাম দ্বারা পরিবর্তনযোগ্য হবে এবং প্রোগ্রাম স্টার্টআপ এবং প্রোগ্রাম সমাপ্তির মধ্যে তাদের শেষ-সঞ্চিত মান বজায় রাখতে পারে।

10) সুতরাং, intসংজ্ঞায়িত টাইপএফ নাম দ্বারা প্রতিস্থাপন করা যেতে পারে int, বা প্রকারের argvমতো লিখতে char **argvপারেন ইত্যাদি।

শেষ বুলেট পয়েন্ট নোট করুন। এটি বলে যে উভয়ই argcএবং argvপরিবর্তনযোগ্য হওয়া উচিত। তাদের পরিবর্তন করতে হবে না, তবে তারা সংশোধন করতে পারে।


মজাদার. একটি আধা-সম্পর্কিত নোটে, আমি একটি ক্র্যাশ-সৃষ্টিকারী বাগের মধ্যে দৌড়ে গেলাম যা প্রমাণিত হয়েছিল যে Qt এর QApplication(argc,argv)নির্মাণকারীর সাথে argcরেফারেন্স দ্বারা সংজ্ঞা দেওয়া হয়েছিল । যা আমাকে অবাক করে দিয়েছিল।
হোস্টাইলফোর্ক বলেছেন

23

argcmain()প্রাক-তারিখের জন্য ফাংশন স্বাক্ষর কারণ সাধারণত একটি ধ্রুবক হয় না const

আরগসি যেহেতু একটি স্ট্যাক ভেরিয়েবল, তাই এটি পরিবর্তন করা আপনার নিজস্ব কমান্ড লাইন প্রক্রিয়াজাতকরণ ব্যতীত অন্য কোনও কিছুকে প্রভাবিত করবে না।

আপনি constচাইলে আপনি অবশ্যই এটি নির্ধারণে মুক্ত ।


8

constএকটি আনুষ্ঠানিক আর্গুমেন্টের শীর্ষ স্তরটি ফাংশন ধরণের অংশ নয়। আপনি এটি যুক্ত করতে বা আপনার পছন্দ মতো অপসারণ করতে পারেন: এটি কেবল ফাংশন বাস্তবায়নে যুক্তির সাথে কী করতে পারে তা প্রভাবিত করে।

সুতরাং আপনার জন্য argcঅবাধে যোগ করতে পারেন const

তবে argvআপনি constযাতে ফাংশনের স্বাক্ষর পরিবর্তন না করে চরিত্রের ডেটা তৈরি করতে পারবেন না । যার অর্থ হ'ল এটি তখন কোনও স্ট্যান্ডার্ড mainফাংশন স্বাক্ষরের নয়, এবং কোনও mainফাংশন হিসাবে স্বীকৃতি পাবে না । সুতরাং, একটি ভাল ধারণা না।


mainখেলনাবিহীন প্রোগ্রামগুলিতে স্ট্যান্ডার্ড আর্গুমেন্ট ব্যবহার না করার একটি ভাল কারণ হ'ল উইন্ডোজে তারা আন্তর্জাতিক অক্ষরের ফাইল ফাইলের মতো বাস্তব প্রোগ্রাম যুক্তি উপস্থাপন করতে সক্ষম হয় না। এটি কারণ উইন্ডোজে তারা খুব শক্তিশালী কনভেনশন দ্বারা উইন্ডোজ এএনএসআই হিসাবে এনকোডেড থাকে। উইন্ডোজ GetCommandLineএআইপি ফাংশনের ক্ষেত্রে আপনি আরও কিছু পোর্টেবল আর্গুমেন্ট অ্যাক্সেস সুবিধা বাস্তবায়ন করতে পারেন ।


সংক্ষেপে বলা যায়, কিছুই আপনাকে যুক্ত constহতে বাধা দেয় না argcতবে সর্বাধিক constউপযোগিতা argvআপনাকে একটি অ-মানক mainফাংশন দেয়, সম্ভবত এটি সম্ভবত স্বীকৃত নয়। সুখেরভাবে (হাস্যকর উপায়ে) পোর্টেবল সিরিয়াস কোডের জন্য স্ট্যান্ডার্ড আর্গুমেন্টগুলি ব্যবহার না করার জন্য ভাল কারণ রয়েছে main। বেশ সহজ, অনুশীলনের জন্য তারা কেবলমাত্র ইংরেজি বর্ণমালার অক্ষরে শুধুমাত্র পুরানো ASCII সমর্থন করে।


1
আপনি যদি সাইগউইন বা অন্য একটি লিবিসি সহ উইন্ডোজের জন্য বিকাশ করছেন যা ইউটিএফ -8 সমর্থন করে যথাযথভাবে সমর্থন করে (যতদূর আমি জানি, বর্তমানে সাইগউইনই একমাত্র তবে আমি অন্য বিকল্পে কাজ করছি এমন একজন), মানক mainস্বাক্ষরটি ঠিকঠাক কাজ করে এবং আপনি পারেন যথেচ্ছ ইউনিকোড যুক্তি গ্রহণ করুন।
আর .. গিটহাব বন্ধ করুন ICE

@ আর তারা বেশিরভাগ * নিক্স প্ল্যাটফর্মগুলিতেও দুর্দান্ত কাজ করে। প্ল্যাটফর্মগুলি যেখানে তারা কাজ করে সেখানে সমস্যা রয়েছে তা নয়। তবে, খুব সুন্দর উদ্যোগ , এবং এটি হওয়ার সাথে সাথে আমি একইভাবে করছি, কমবেশি গুরুত্ব সহকারে
চিয়ার্স এবং এইচটিএস। - Alf

4

এর স্বাক্ষর mainকিছুটা historicalতিহাসিক নিদর্শন থেকে C। .তিহাসিকভাবে Cছিল না const

তবে constকনস্টের প্রভাবগুলি কেবল সংকলন করার কারণে আপনি আপনার প্যারামিটারটি ঘোষণা করতে পারেন ।


আপনি যখন "Cতিহাসিক সি" বলবেন আমরা এখানে কতটা historicalতিহাসিক কথা বলছি?
জো জেড

8
constসি 89 / সি 90 এ যুক্ত হয়েছিল; তার আগে, এটি সি এর অংশ ছিল না
জোনাথন লেফলার

@ জোনাথনলফলার: আপনি জানেন, আমি তা ভুলে গিয়েছিলাম। আমি ১৯৯২ সালে সি শিখেছি that
জো জেড

2

কারণ argcএকটি স্থানীয় পরিবর্তনশীল (এবং, সি ++ এ, কোনও রেফারেন্স বা কিছু নয়) এবং mainকারণটির বিশেষ স্থানটি হ'ল পিছনের দিকের সামঞ্জস্যতা শেননিগানরা এটিকে অ্যাপ্লিকেশনকে বাধ্য করতে বাধ্য করার মতো কোনও বাধ্যবাধকতা ছাড়াই এটিকে বিশাল পরিমাণ ছাড় দেয় e

main() {}

int main() {}

main() { return 0; }

main(int argc, char* argv[]) { return 0; }

int main(const int argc, const char** argv) { /* no return*/ }

এই এবং অন্যান্য অনেকগুলি প্রকারভেদ বিস্তৃত সি এবং সি ++ সংকলকগুলিতে সংকলন করবে।

সুতরাং শেষ পর্যন্ত এটি আরকসিটি কনস্ট নয়, কেবল এটির দরকার নেই, তবে এটি হতে পারে যদি আপনি এটি চান।

http://ideone.com/FKldHF , সি উদাহরণ:

main(const int argc, const char* argv[]) { return 0; }

http://ideone.com/m1qc9c , সি ++ উদাহরণ

main(const int argc) {}

দ্রষ্টব্য যে সুস্পষ্ট রিটার্ন টাইপ ব্যতীত রূপগুলি C99 তে আর কার্যকর হবে না, তবে সি 11 ছেড়ে দিন, যদিও সংযোজকগুলি পিছনের দিকের সামঞ্জস্যের কারণে তাদের অনুমতি দেয়। সি ++ সংকলকগুলির কোনও রিটার্নের ধরণ ছাড়াই বৈকল্পিকগুলি গ্রহণ করা উচিত নয়।
জোনাথন লেফলার

@ জোনাথনলফলার হ্যাঁ, এখনও সেখানে সর্বশেষ আদর্শের আদর্শ (আদর্শ one.com/m1qc9c ) জি ++ ৪.৮.২ সহ -std=c++11। বিড়ম্বনা এটিও গ্রহণ করে তবে দেয় warning: only one parameter on 'main' declaration [-Wmain]এবং এমএসভিসি কেবল অনুপস্থিত রিটার্ন টাইপের নির্দিষ্টকারক এবং আরজকের কোনও উল্লেখের অভাব সম্পর্কে প্রতিবাদ করে। আবার '
শেনানিগানস

1

Reasonsতিহাসিক কারণগুলি বাদে, আরগসি এবং আরজিভি অকেজো রাখার একটি ভাল কারণ constহ'ল সংকলক বাস্তবায়ন জানে না আপনি মূল আর্গুমেন্টগুলি দিয়ে কী করতে যাচ্ছেন, এটি কেবল জানে যে এটি আপনাকে অবশ্যই এই আর্গুমেন্টগুলি দিতে হবে।

আপনি যখন নিজের ফাংশন এবং সম্পর্কিত প্রোটোটাইপগুলি সংজ্ঞায়িত করছেন, আপনি জানেন যে আপনি কোন প্যারামিটার তৈরি করতে পারেন constএবং কোনটি আপনার ফাংশনটি সংশোধন করবে।

চূড়ান্তভাবে নিয়ে যাওয়া, আপনি ঘোষণা করতে পারেন যে সমস্ত ফাংশনের সমস্ত প্যারামিটারগুলি ঘোষণা করা উচিত constএবং তারপরে যদি আপনার সেগুলি পরিবর্তন করার কোনও কারণ থাকে (উদাহরণস্বরূপ একটি অ্যারের মাধ্যমে অনুসন্ধান করার জন্য একটি সূচক হ্রাস করা), আপনাকে স্থানীয় অ- constপরিবর্তনশীল করতে হবে এবং constআর্গুমেন্টগুলির মানগুলি সেই ভেরিয়েবলগুলিতে অনুলিপি করুন । এটি ব্যস্ত-কাজের জন্য এবং কোনও আসল সুবিধা ছাড়াই অতিরিক্ত এলওসি তৈরি করে। আপনি যদি কোনও যুক্তির মান পরিবর্তন না করে থাকেন তবে কোনও শালীন স্ট্যাটিক বিশ্লেষক আপনাকে বেছে নেবে এবং আপনাকে প্যারামিটার তৈরি করার পরামর্শ দেয় const

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.