আমার কি চর ** আরজিভি বা চর * আরগভি [] ব্যবহার করা উচিত?


125

আমি কেবল সি শিখছি এবং ভাবছিলাম যে এর মধ্যে কোনটি আমার প্রধান পদ্ধতিতে ব্যবহার করা উচিত। কোন পার্থক্য আছে? কোনটি বেশি সাধারণ?


2
আমি 'চর ** আরজিভি' পছন্দ করি, এবং তাই আমি এটিকে আরও প্রায়ই দেখি তবে উভয়ই সঠিক এবং এটি 'চর * আরগভ []' লেখা হয়েছিল বলেই আমি কোনও ঘোষণা পরিবর্তন করব না।
জোনাথন লেফলার

+1 কারণ অ্যারে বনাম পয়েন্টারের গভীর সমস্যাগুলি ভালভাবে বুঝতে গুরুত্বপূর্ণ।
আরবেরটিগ

2
সত্যিই, সত্যিই ভাল প্রশ্ন। ধন্যবাদ.
ফ্রাঙ্ক ভি

5
কমপ্লেক্স.এফএইউএর 6 টি বিভাগ পড়ুন ; এটি আমি দেখেছি সি অ্যারে এবং পয়েন্টারগুলির মধ্যে সম্পর্কের সেরা ব্যাখ্যা। দুটি প্রাসঙ্গিক বিষয়: ১. পরামিতি ঘোষণার (এবং কেবলমাত্র প্যারামিটারের ঘোষণা হিসাবে) char **argvসমান । 2. অ্যারে পয়েন্টার নয়। char *argv[]
কিথ থমসন

উত্তর:


160

আপনি যেমন সি শিখছেন, আমি আপনাকে সুপারিশ করছি সাধারণ জিনিসগুলির পরিবর্তে প্রথমে অ্যারে এবং পয়েন্টারগুলির মধ্যে পার্থক্যগুলি বোঝার চেষ্টা করুন ।

প্যারামিটার এবং অ্যারেগুলির ক্ষেত্রে কয়েকটি বিভ্রান্তিকর নিয়ম রয়েছে যা চালানোর আগে পরিষ্কার হওয়া উচিত। প্রথমত, আপনি প্যারামিটার তালিকায় যা ঘোষণা করেন তা বিশেষ বিবেচিত হয়। এমন পরিস্থিতি রয়েছে যেখানে সিগুলিতে কোনও ফাংশন প্যারামিটার হিসাবে জিনিসগুলি বোঝায় না 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;

2
এটি উপস্থিত থাকার কোনও ধারণা ছিল না: *
আরজিভি

12

আপনি হয় ব্যবহার করতে পারেন। তারা সম্পূর্ণ সমতুল্য। দেখুন 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;
}

যার জন্য বেশি সাধারণ - তাতে কিছু আসে যায় না। আপনার কোড পড়ার যে কোনও অভিজ্ঞ সি প্রোগ্রামার উভয়ই বিনিময়যোগ্য (সঠিক অবস্থার অধীনে) দেখতে পাবে। ঠিক তেমনি একজন অভিজ্ঞ ইংরেজী স্পিকার যেমন "তারা" এবং "তারা" সমানভাবে সহজেই পড়ে।

আরও গুরুত্বপূর্ণ হ'ল আপনি সেগুলি পড়তে শিখুন এবং সেগুলি কতটা সাদৃশ্য তা স্বীকৃতি দিন। আপনি লেখার চেয়ে আরও কোড পড়বেন এবং আপনার উভয়ের সাথে সমান স্বাচ্ছন্দ্য বোধ করা দরকার।


7
গৃহস্থালি * আরগভি [] একটি ফাংশনের প্যারামিটার ধরণের হিসাবে ব্যবহৃত হলে চর ** আরগভের 100% সমতুল্য। কোনও "কনস্ট্যান্ট" জড়িত, নিখুঁতভাবেও নয়। উভয়ই অক্ষরের প্রতি নির্দেশক। আপনি যা ঘোষণা করেন সে ক্ষেত্রে এটি আলাদা। তবে সংকলক পয়েন্টারের সাথে পয়েন্টার হওয়ার জন্য প্যারামিটারের প্রকারটি সামঞ্জস্য করে, যদিও আপনি এটি অ্যারে বলেছেন। সুতরাং, নিম্নলিখিতগুলি একই রকম: অকার্যকর চ (চর * পি [100]); অকার্যকর চ (চর * পি []); অকার্যকর চ (চর ** পি);
জোহানেস স্কাউব -

4
C89 তে (যা বেশিরভাগ লোকেরা ব্যবহার করে) আপনি এটিকে অ্যারে হিসাবে ঘোষিত করেছেন এর সুবিধা নেওয়ার কোনও উপায় নেই (সুতরাং শব্দার্থিকভাবে আপনি সেখানে পয়েন্টার বা অ্যারে ঘোষণা করেছেন কিনা তা বিবেচ্য নয় - উভয়ই গ্রহণ করা হবে পয়েন্টার)। C99 দিয়ে শুরু করে, আপনি এটিকে অ্যারে হিসাবে ঘোষণা করে উপকৃত হতে পারেন। নিম্নলিখিতটি বলে: "পি সর্বদা অ-নাল এবং কমপক্ষে 100 বাইটস বিশিষ্ট অঞ্চলকে নির্দেশ করে": অকার্যকর চ (চর পি [স্ট্যাটিক 100]); নোট করুন যে প্রকার অনুসারে, তবে পি এখনও একটি পয়েন্টার।
জোহানেস স্কাউব -

5
(বিশেষত, এবং পি আপনাকে একটি চর প্রদান করবে **, তবে চর নয় ( ) [100] যা পি * এর অ্যারে হলে কেস হবে ))। আমি এখনও উত্তরে কারও উল্লেখ না করে অবাক হয়েছি। আমি এটি বুঝতে খুব গুরুত্বপূর্ণ হিসাবে বিবেচনা।
জোহানেস স্কাউব -

ব্যক্তিগতভাবে আমি পছন্দ করি char**কারণ এটি আমাকে মনে করিয়ে দেয় যে এটি করার মতো সত্যিকারের অ্যারে হিসাবে আচরণ করা উচিত নয় sizeof[arr] / sizeof[*arr]
raymai97

9

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


9

আপনি দুটি ফর্মের মধ্যে দুটি ব্যবহার করতে পারেন, যেমন সি অ্যারে এবং পয়েন্টারগুলি ফাংশন প্যারামিটার তালিকায় বিনিময়যোগ্য। Http://en.wikedia.org/wiki/C_( প্রোগ্রামিং_এলংয়েজ)) দেখুন: অ্যারে- পয়েন্টার_ইন্টারচেঞ্জেবিলিটি


4

এটি আসলে কোনও পার্থক্য করে না, তবে আধুনিকটি আরও বেশি পঠনযোগ্য। আপনাকে যা দেওয়া হয় তা হ'ল চর পয়েন্টারগুলির একটি অ্যারে, যেমন দ্বিতীয় সংস্করণ বলে। এটি প্রথম ভার্সনের মতোই স্পষ্টভাবে ডাবল চর পয়েন্টারে রূপান্তরিত হতে পারে।


2

আপনার এটি হিসাবে ঘোষণা করা উচিত char *argv[], কারণ এটি ঘোষণার সমস্ত সমতুল্য পদ্ধতির কারণে এটি এর স্বজ্ঞাত অর্থের নিকটে আসে: স্ট্রিংগুলির একটি অ্যারে।


1

চর ** character চরিত্র পয়েন্টার থেকে পয়েন্টার এবং চর * আরগভি [] এর অর্থ চরিত্র পয়েন্টারের অ্যারে। যেহেতু আমরা অ্যারের পরিবর্তে পয়েন্টার ব্যবহার করতে পারি, উভয়ই ব্যবহার করা যায়।


0

আমি অন্যটির পরিবর্তে উভয়ই পদ্ধতির ব্যবহারের বিশেষ যোগ্যতা দেখছি না - আপনার কোডটির বাকী কোডের সাথে সাদৃশ্যপূর্ণ কনভেনশনটি ব্যবহার করুন।


-2

আপনার যদি ভিন্ন ভিন্ন বা গতিশীল স্ট্রিংগুলির প্রয়োজন হয় তবে চর ** এর সাথে কাজ করা আরও সহজ হতে পারে। আপনার স্ট্রিংয়ের সংখ্যা যদি স্থির থাকে তবে চর * var [] পছন্দ করা হবে।


-2

আমি জানি এটি পুরানো, তবে আপনি যদি কেবল সি প্রোগ্রামিং ভাষা শিখতে থাকেন এবং এর সাথে বড় কিছু করেন না, কমান্ড-লাইন বিকল্পগুলি ব্যবহার করবেন না।

আপনি যদি কমান্ড লাইন যুক্তি ব্যবহার না করে থাকেন তবে তা ব্যবহার করবেন না। শুধু হিসাবে int main() আপনি মূল ফাংশন ঘোষণা

  • আপনার প্রোগ্রামটির ব্যবহারকারী আপনার ফাইলটিতে একটি ফাইল টেনে আনতে সক্ষম হন যাতে আপনি এটির সাথে আপনার প্রোগ্রামের ফলাফল পরিবর্তন করতে পারেন বা
  • কমান্ড-লাইন বিকল্পগুলি ( -help, /?বা program nameটার্মিনাল বা কমান্ড প্রম্পটে পরবর্তী যে কোনও জিনিস ) পরিচালনা করতে চান

আপনার যেটি আরও বেশি বোঝায় তা ব্যবহার করুন। অন্যথায়, int main() সর্বোপরি ব্যবহার করুন, আপনি যদি কমান্ড-লাইন বিকল্পগুলি যুক্ত করতে চান তবে আপনি এগুলিকে পরে এডিট করতে পারবেন।


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