কেন সি / সি ++ প্রধান আরগভিটিকে কেবল "চর * আরগভি" না করে "চর * আরজিভি []" হিসাবে ঘোষণা করা হচ্ছে?


21

কেন argvহিসাবে "একটি অ্যারের প্রথম সূচক পয়েন্টার পয়েন্টার", বদলে শুধু হচ্ছে "একটি পয়েন্টার অ্যারের প্রথম সূচক" (ঘোষিত char* argv)?

"পয়েন্টার থেকে পয়েন্টার" ধারণাটি এখানে কেন প্রয়োজনীয়?


4
"অ্যারের প্রথম সূচক পয়েন্টার একটি পয়েন্টার" - যে একটি সঠিক বর্ণনা নয় char* argv[]বা char**। এটি একটি চরিত্রের পয়েন্টারটির পয়েন্টার; বিশেষত বাহ্যিক পয়েন্টার একটি অ্যারের প্রথম পয়েন্টারটিতে নির্দেশ করে এবং অভ্যন্তরীণ পয়েন্টারগুলি নুল-টার্মিনেটেড স্ট্রিংগুলির প্রথম অক্ষরগুলিতে নির্দেশ করে। এখানে কোনও সূচক জড়িত নেই।
সেবাস্তিয়ান রেডল

12
আপনি যদি দ্বিতীয় যুক্তিটি পেয়ে যাবেন তবে এটি কেবল চর * আরগভি ছিল?
gnasher729

15
আপনি জায়গাটি সঠিক জায়গায় রাখলে আপনার জীবন আরও সহজ হবে। char* argv[]স্থান ভুল জায়গায় রাখে। বলুন char *argv[], এবং এখন এটি স্পষ্ট হয়ে গেছে যে এর অর্থ "এক্সপ্রেশনটি *argv[n]টাইপের একটি পরিবর্তনশীল char"। কোনও পয়েন্টার কী এবং কোনও পয়েন্টারটিতে কীসের ইঙ্গিত দেয় এবং এগুলি নিয়ে কাজ করার চেষ্টা করে আটকে যাবেন না। ঘোষণাপত্রে আপনাকে জানানো হচ্ছে যে আপনি এই জিনিসটিতে কী পরিচালনা করতে পারেন।
এরিক লিপার্ট

1
মানসিকভাবে char * argv[]অনুরূপ সি ++ কনস্ট্রাক্টের সাথে তুলনা করুন std::string argv[]এবং এটি পার্স করা আরও সহজ হতে পারে। ... ঠিক এভাবে লেখা শুরু করবেন না !
জাস্টিন টাইম 2 মনিকা

2
@ এরিকলিপার্ট নোট করুন যে প্রশ্নটিতে সি ++ অন্তর্ভুক্ত রয়েছে এবং সেখানে আপনার উদাহরণ থাকতে পারে char &func(int);যা &func(5)টাইপ করে না char
রুসলান

উত্তর:


59

আরগভি মূলত এরকম:

এখানে চিত্র বর্ণনা লিখুন

বামদিকে আর্গুমেন্টটি নিজেই রয়েছে - যা আসলে প্রধান হিসাবে একটি আর্গুমেন্ট হিসাবে পাস করেছে। এটিতে পয়েন্টারগুলির একটি অ্যারের ঠিকানা রয়েছে। কমান্ড লাইনে পাস হওয়া সংশ্লিষ্ট আর্গুমেন্টের পাঠ্য ধারণ করে মেমরির সেই জায়গাগুলির প্রত্যেকটিই নির্দেশ করে। তারপরে, অ্যারের শেষে একটি নাল পয়েন্টার হওয়ার নিশ্চয়তা রয়েছে।

নোট করুন যে পৃথক যুক্তিগুলির জন্য প্রকৃত সঞ্চয়স্থান কমপক্ষে একে অপরের থেকে পৃথকভাবে বরাদ্দ করা হয়, সুতরাং স্মৃতিতে তাদের ঠিকানাগুলি যথাযথভাবে এলোমেলোভাবে সাজানো যেতে পারে (তবে কীভাবে বিষয়গুলি লিখিত হতে পারে তার উপর নির্ভর করে সেগুলি একটি একক সংলগ্ন ব্লকেও থাকতে পারে মেমরি - আপনি কেবল জানেন না এবং যত্ন করা উচিত নয়)।


52
আপনার জন্য যে লেআউট ইঞ্জিনটি আঁকার চিত্রটি এনেছে তাদের মিনিমাইজ-ক্রসিং অ্যালগরিদমে একটি বাগ আছে!
এরিক লিপার্ট

43
@ এরিকলিপার্ট জোর দিয়ে উদ্দেশ্যমূলক হতে পারে যে পয়েন্টগুলি সামঞ্জস্যপূর্ণ বা যথাযথ নাও হতে পারে।
জেমসডলিন

3
আমি এটি ইচ্ছাকৃত বলব
মাইকেল

24
এটি অবশ্যই উদ্দেশ্যমূলক ছিল - এবং আমি অনুমান করেছিলাম এরিক সম্ভবত এটি বুঝতে পেরেছিল, তবে (সঠিকভাবে, আইএমও) ভেবেছিল মন্তব্যটি যাইহোক মজার ছিল।
জেরি কফিন

2
@ জেরি কফিন, কেউ এটিও উল্লেখ করতে পারে যে প্রকৃত যুক্তিগুলি মেমরির ক্ষেত্রে সামঞ্জস্যপূর্ণ থাকলেও তাদের নির্বিচারে দৈর্ঘ্য থাকতে পারে, সুতরাং argv[i]পূর্ববর্তী সমস্তগুলি স্ক্যান না করেই তাদের প্রত্যেককে অ্যাক্সেস করতে সক্ষম হওয়ার জন্য আলাদা আলাদা পয়েন্টার প্রয়োজন ।
ইল্কচাচু

22

কারণ এটি অপারেটিং সিস্টেমটি প্রদান করে :-)

আপনার প্রশ্নটি একটি মুরগির / ডিমের বিপরীতে ইস্যুটির সামান্য কিছু। সমস্যাটি আপনি সি ++ এ যা চান তা চয়ন করার নয়, ওএস আপনাকে যা দিচ্ছে তা আপনি সি ++ এ কীভাবে বলছেন তা সমস্যা।

ইউনিক্স "স্ট্রিংস" এর অ্যারে পাস করে, প্রতিটি স্ট্রিং কমান্ড আর্গুমেন্ট। সি / সি ++ এ, একটি স্ট্রিং হ'ল "চর *", সুতরাং স্ট্রিংগুলির একটি অ্যারে হল স্বাদ অনুসারে চর * আরগভি [], বা চর ** আরজিভি।


13
না, এটি হ'ল "আপনি সি ++ তে যা চান তা চয়ন করতে সমস্যা"। উইন্ডোজ উদাহরণস্বরূপ, কমান্ড লাইনটি একটি একক স্ট্রিং হিসাবে উপলব্ধ করে, এবং তবুও সি / সি ++ প্রোগ্রামগুলি এখনও তাদের argvঅ্যারে গ্রহণ করে - রানটাইম শুরুতে কমান্ড লাইনটি টোকিনাইজ করার এবং argvঅ্যারে তৈরির যত্ন নেয় ।
জোকার_ভিডি

14
@ জোকার_ভিডি আমি ওএস আপনাকে যা দেবে সে সম্পর্কে এটি একটি বাঁকানো ভাবি । বিশেষত: আমার ধারণা, সি ++ এটি এইভাবে করেছিল কারণ সি এটি এইভাবে করেছিল, এবং সি এটি এইভাবে করেছিল কারণ সেই সময় সি এবং ইউনিক্স এতটা সংক্ষিপ্তভাবে যুক্ত ছিল এবং ইউনিক্স এটি এইভাবে করেছিল।
ড্যানিয়েল ওয়াগনার

1
@ ড্যানিয়েল ওয়াগনার: হ্যাঁ, এটি সি এর ইউনিক্স heritageতিহ্য থেকে এসেছে। ইউনিক্স / লিনাক্সে এমন একটি ন্যূনতম _startকল যা mainকেবলমাত্র মেমরির mainবিদ্যমান argvঅ্যারেটিতে একটি পয়েন্টার পাস করতে পারে ; এটি ইতিমধ্যে সঠিক ফর্ম্যাটে রয়েছে। কার্নেল এটি আরগভ আর্গুমেন্ট থেকে execve(const char *filename, char *const argv[], char *const envp[])সিস্টেম কলটিতে অনুলিপি করে যা একটি নতুন এক্সিকিউটেবল শুরু করার জন্য তৈরি হয়েছিল। (লিনাক্সে, আরজিভি [] (অ্যারে নিজেই) এবং আরগিসি প্রক্রিয়া প্রবেশের স্ট্যাকের মধ্যে রয়েছে I আমি বেশিরভাগ ইউনিক্স একই হিসাবে ধরে নিয়েছি, কারণ এটি এটির জন্য একটি ভাল জায়গা))
পিটার কর্ডেস

8
তবে এখানে জোকারের বক্তব্যটি হ'ল সি / সি ++ স্ট্যান্ডার্ডগুলি প্রয়োগগুলি যেখানে আর্গুমেন্টগুলি এসেছে সেগুলি পর্যন্ত ছেড়ে দেয়; ওএস থেকে তাদের সোজা হতে হবে না। কোনও ওএসে যা একটি ফ্ল্যাট স্ট্রিং পাস করে, একটি ভাল সি ++ বাস্তবায়নের argc=2মধ্যে পুরো ফ্ল্যাট স্ট্রিংটি সেট এবং পাস করার পরিবর্তে টোকেনাইজিং অন্তর্ভুক্ত করা উচিত । (স্ট্যান্ডার্ডের অক্ষর অনুসরণ করা দরকারী হিসাবে যথেষ্ট নয় ; এটি ইচ্ছাকৃতভাবে প্রয়োগের পছন্দগুলির জন্য প্রচুর জায়গা ছেড়ে দেয়।) যদিও কিছু উইন্ডোজ প্রোগ্রামগুলি বিশেষভাবে উদ্ধৃতিগুলি ব্যবহার করতে চাইবে, তাই বাস্তব বাস্তবায়নগুলি ফ্ল্যাট স্ট্রিং পাওয়ার উপায় সরবরাহ করে, খুব।
পিটার কর্ডেস

1
বেসিলের উত্তরটি আরও + + জোকারের সংশোধন এবং আরও মন্তব্য সহ আমার মন্তব্যগুলি বেশ সুন্দর pretty
পিটার কর্ডেস

15

প্রথমত, প্যারামিটারের ঘোষণা char **argvহিসাবে একই char *argv[]; তারা উভয় স্ট্রিংগুলিতে একটি পয়েন্টার (একটি অ্যারে বা একাধিক সম্ভাব্য সংখ্যার সেট) নির্দেশককে বোঝায়।

এর পরে, যদি আপনার কাছে কেবল "চরের দিকে নির্দেশক" থাকে - যেমন ঠিক char *- তবে নবম আইটেমটি অ্যাক্সেস করতে আপনাকে নবম আইটেমটির শুরুতে প্রথম এন -1 আইটেমটি স্ক্যান করতে হবে। (এবং এটি প্রতিটি স্ট্রিং স্বচ্ছলভাবে সংরক্ষণ করা প্রয়োজনও চাপিয়ে দেবে))

পয়েন্টারের অ্যারে দিয়ে আপনি সরাসরি নবম আইটেমটি সূচক করতে পারেন - সুতরাং (কঠোরভাবে প্রয়োজনীয় না হলেও - স্ট্রিংগুলি স্বচ্ছ মনে করে) এটি সাধারণত আরও সুবিধাজনক।

বর্ণনা করা:

। / প্রোগ্রাম হ্যালো ওয়ার্ল্ড

argc = 3
argv[0] --> "./program\0"
argv[1] --> "hello\0"
argv[2] --> "world\0"

এটি সম্ভব যে কোনও ওএস-এ অক্ষর সরবরাহ করা হয়েছে:

            "./program\0hello\0world\0"
argv[0]      ^
argv[1]                 ^
argv[2]                        ^

যদি আরগভিটি কেবল "চরকে নির্দেশক" হত তবে আপনি দেখতে পাচ্ছেন

       "./program\0hello\0world\0"
argv    ^

তবে (যদিও ওএসের নকশা অনুসারে) তিনটি স্ট্রিং "./pogram", "হ্যালো" এবং "ওয়ার্ল্ড" সামঞ্জস্যপূর্ণ হওয়ার কোনও সত্য গ্যারান্টি নেই। তদুপরি, এই জাতীয় "একাধিক সংলগ্ন স্ট্রিংগুলিতে একক পয়েন্টার" একটি বিশেষত স্ট্রিং-এর পয়েন্টারের অ্যারের সাথে তুলনা করে (সি এর জন্য) আরও অস্বাভাবিক ডাটা টাইপ কনস্ট্রাক্ট।


পরিবর্তে যদি হয় তবে argv --> "hello\0world\0"আপনার কাছে argv --> index 0 of the array(হ্যালো) ঠিক আছে সাধারণ অ্যারের মতো। কেন এটি করণীয় নয়? তারপরে আপনি অ্যারের argcসময়গুলি পড়তে থাকুন । তারপরে আপনি আরগভি নিজেই পাস করেন এবং আরগভিতে কোনও পয়েন্টার নয়।
একজন ব্যবহারকারী

@ কারণ, এটিই আর্গভ -> "./program\0hello\0\world\0" হ'ল: প্রথম চরের পয়েন্টার (অর্থাত ""। ") আপনি যদি সেই পয়েন্টারটিকে প্রথম \ 0 এর আগে নিয়ে যান তবে আপনি "হ্যালো \ 0", এবং এর পরে "ওয়ার্ল্ড \ 0" এর পয়েন্টার রাখুন। আরগ বার করার পরে (\ 0 "টিপে) আপনি কাজটি করেছেন। অবশ্যই, এটি কাজ করা যায়, এবং আমি যেমন বলেছিলাম একটি অস্বাভাবিক নির্মাণ
এরিক tদ

আপনি উল্লেখ করতে ভুলে গেছেন যে আপনার উদাহরণটি argv[4]হ'লNULL
বেসাইল স্টারিনকিভিচ

3
একটি গ্যারান্টি আছে যে (কমপক্ষে প্রাথমিকভাবে) argv[argc] == NULL। এই ক্ষেত্রে argv[3], না argv[4]
মিরাল

1
@ হিল, হ্যাঁ, ধন্যবাদ যেমন আমি নাল চরিত্রের টার্মিনেটরগুলি সম্পর্কে স্পষ্ট করে দেওয়ার চেষ্টা করছিলাম (এবং এটিটি মিস করেছি)।
এরিক tদ

13

কেন সি / সি ++ প্রধান আরগভিটিকে "চর * আরজিভি []" হিসাবে ঘোষণা করা হয়েছে?

একটি সম্ভাব্য উত্তর কারণ C11 মান n1570 (ইন §5.1.2.2.1 প্রোগ্রাম প্রারম্ভে ) এবং সি ++ 11 মান n3337 (ইন §3.6.1 প্রধান ফাংশন ) প্রয়োজন যে হোস্ট পরিবেশের জন্য (কিন্তু নোটিশ সি মান উল্লেখ করেছেন যে এছাড়াও §5.1.2.1 freestanding পরিবেশের এছাড়াও) দেখতে এই

পরবর্তী প্রশ্ন হ'ল কেন সি এবং সি ++ স্ট্যান্ডার্ড কেন mainএই জাতীয় int main(int argc, char**argv)স্বাক্ষর রাখতে বেছে নিয়েছিল? ব্যাখ্যাটি মূলত historical তিহাসিক : সি ইউনিক্স দ্বারা উদ্ভাবিত হয়েছিল , যার শেল রয়েছে যা করার আগে গ্লোব্বিং করে fork(যা একটি প্রক্রিয়া তৈরি করার জন্য সিস্টেম কল) এবং execve(যা একটি প্রোগ্রাম চালানোর জন্য সিস্টেম কল), এবং এটি execveঅ্যারে সংক্রমণ করে স্ট্রিং প্রোগ্রামের আর্গুমেন্টগুলির এবং mainএটি সম্পাদিত প্রোগ্রামের সাথে সম্পর্কিত । ইউনিক্স দর্শন এবং এবিআই এর সম্পর্কে আরও পড়ুন ।

এবং সি ++ সি এর সম্মেলনগুলি অনুসরণ করার এবং এর সাথে সামঞ্জস্য করার জন্য কঠোর চেষ্টা করেছিল। এটি mainসি traditionsতিহ্যের সাথে বেমানান হতে সংজ্ঞায়িত করতে পারেনি ।

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

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


12

এটিকে "পয়েন্টার থেকে পয়েন্টার" হিসাবে ভাবার পরিবর্তে এটি "স্ট্রিংগুলির অ্যারে" হিসাবে ভাবতে সহায়তা করে, []অ্যারে char*ডোনোটিং এবং স্ট্রোককে বোঝায়। যখন আপনি একটি প্রোগ্রাম চালানো, আপনি এটি এক বা একাধিক কমান্ড লাইন আর্গুমেন্ট পাস করতে পারেন এবং এই আর্গুমেন্ট মধ্যে প্রতিফলিত হয় main: argcআর্গুমেন্ট গণনা এবং argvআপনাকে নির্দিষ্ট আর্গুমেন্ট অ্যাক্সেস করতে দেয়।


2
+1 এটি! অনেক ভাষায় - ব্যাশ, পিএইচপি, সি, সি ++ - আরজিভি স্ট্রিংগুলির একটি অ্যারে। এর মধ্যে আপনাকে কখন দেখতে হবে char **বা কখন তা দেখতে হবে তা ভাবতে হবে char *[]
রেক্সকোগিটানস

1

অনেক ক্ষেত্রে উত্তরটি "কারণ এটি একটি মান"। C99 মানটি উদ্ধৃত করতে :

- যদি আরগিসির মান শূন্যের চেয়ে বেশি হয় তবে অ্যারে সদস্যগণ আরজিভি [0] এর মাধ্যমে আরজিভি [আরজিসি -১] সহ অন্তর্ভুক্তিতে স্ট্রিংগুলিতে পয়েন্টার যুক্ত থাকতে পারে , যা প্রোগ্রাম শুরুর আগে হোস্ট পরিবেশের দ্বারা প্রয়োগ-সংজ্ঞায়িত মান দেওয়া হয়।

অবশ্যই, আগে এটি মান নির্ধারিত করা হয়েছে এটা তাড়াতাড়ি ইউনিক্স বাস্তবায়নের মধ্যে K & R এর C দ্বারা ইতিমধ্যে ব্যবহারে ছিল কম্যান্ড-লাইন পরামিতি জমা করার উদ্দেশ্য সঙ্গে (কোন কিছু যা আপনি ইউনিক্স মধ্যে পরোয়া করতে হবে যেমন শেল /bin/bashবা /bin/shএমবেডেড সিস্টেম কিন্তু নয়)। কে অ্যান্ড আর এর "দ্য সি প্রোগ্রামিং ল্যাঙ্গুয়েজ" (পৃষ্ঠা 110) এর প্রথম সংস্করণটি উদ্ধৃত করতে :

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

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