অ্যারে, পয়েন্টার এবং ফাংশনগুলির জন্য কেন সি সিনট্যাক্সটি এভাবে ডিজাইন করা হয়েছিল?


16

দেখার পরে (এবং জিজ্ঞাসা!) অনুরূপ অনেক প্রশ্ন

int (*f)(int (*a)[5])সি এর অর্থ কী ?

এমনকি তারা সি-সিনট্যাক্স বুঝতে লোকদের সহায়তা করার জন্য একটি প্রোগ্রাম তৈরি করেছেন তা দেখেও আমি আর আশ্চর্য হতে পারি না:

সি এর সিনট্যাক্সটি এভাবে ডিজাইন করা হয়েছিল কেন?

উদাহরণস্বরূপ, যদি আমি পয়েন্টারগুলি ডিজাইন করছিলাম তবে আমি "পয়েন্টারগুলিকে পয়েন্টারগুলির 10-এলিমেন্ট অ্যারেতে" অনুবাদ করব

int*[10]* p;

এবং না

int* (*p)[10];

যা আমি মনে করি বেশিরভাগ লোকেরা একমত হবেন এটি খুব কম সোজা।

সুতরাং আমি ভাবছি, কেন, উহ, অনিচ্ছাকৃত সিনট্যাক্স? সিনট্যাক্স সমাধান করে এমন কোনও নির্দিষ্ট সমস্যা ছিল (সম্ভবত কোনও দ্বিপাক্ষা?) যার সম্পর্কে আমি অজানা?


2
আপনি জানেন যে এটির এবং এই জাতীয় প্রশ্নের কোনও সত্যিকারের উত্তর নেই। রাইট? আপনি যা পাবেন তা কেবল অনুমান।
BЈовић

7
@ ভিজেও - একটি "প্রকৃত" (অর্থাত্ উদ্দেশ্যমূলক) উত্তর থাকতে পারে - ভাষা লেখক এবং মানক কমিটিগুলি উভয়ই এই সিদ্ধান্তগুলির সুস্পষ্টভাবে ন্যায়সঙ্গত (বা কমপক্ষে ব্যাখ্যা করেছেন)।
অবধি

আমি মনে করি না আপনার প্রস্তাবিত বাক্য গঠন সি সিনট্যাক্সের চেয়ে কম বেশি "স্বজ্ঞাত"। সি এটা কি; একবার আপনি এটি জানতে পেরে গেলে, আপনার আর কখনও এই প্রশ্নগুলি হবে না। যদি আপনি এটি না শিখে থাকেন ... ভাল, সম্ভবত এটিই আসল সমস্যা।
কালেব

1
@ কালেব: আপনি কীভাবে এত সহজেই এই সিদ্ধান্তে পৌঁছেছিলেন তা মজার বিষয়, কারণ আমি এটি শিখেছি এবং এখনও আমার এই প্রশ্নটি ছিল ...
ব্যবহারকারীর 41১4168686

1
cdeclকমান্ড জটিল সি ঘোষণা ডিকোডিং জন্য খুবই সুবিধাজনক। সিডেকএল.আরজে একটি ওয়েব ইন্টারফেসও রয়েছে ।
কিথ থম্পসন

উত্তর:


16

এর ইতিহাস সম্পর্কে আমার বোধগম্যতা এটি দুটি প্রধান পয়েন্টের ভিত্তিতে ...

প্রথমত, ভাষার লেখকরা টাইপ-কেন্দ্রিকের চেয়ে সিনট্যাক্সকে পরিবর্তনশীল-কেন্দ্রিক তৈরি করতে পছন্দ করেন। এটি হ'ল, তারা একটি প্রোগ্রামার ঘোষণাপত্রটি দেখতে চেয়েছিল এবং মনে করে "যদি আমি প্রকাশটি লিখি *func(arg), এর ফলস্বরূপ int; আমি যদি লিখি তবে আমার *arg[N]একটি ভাসমান" না হয়ে " funcঅবশ্যই এই ফাংশনের পয়েন্টার হতে হবে এবং ফিরে যে "।

উইকিপিডিয়ায় সি এন্ট্রি দাবী করেন যে:

রিচির ধারণা ছিল তাদের ব্যবহারের সাথে সাদৃশ্যযুক্ত প্রেক্ষাপটে সনাক্তকারীদের ঘোষণা করা: "ঘোষণাপত্রের ব্যবহার প্রতিফলিত করে"।

... কে ও আর 2 এর পি 122 উদ্ধৃত করে যা আফসোস, আপনার জন্য বর্ধিত উদ্ধৃতি সন্ধানের জন্য আমাকে হাত দিতে হবে না।

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

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

এই বলে যে, আমি ভাষার ব্যাকরণ বা সংকলক রচনায় বিশেষজ্ঞ নই। তবে আমি জানার মতো অনেক কিছুই জানতে পারি;)


2
"কম্পাইলারগুলি লিখতে সহজ করে তোলা" ... সি ব্যতীত কঠিন হওয়ার কারণে কুখ্যাত (শুধুমাত্র সি ++ দ্বারা শীর্ষে রয়েছে)।
জানু হুডেক

1
@ জানহুদেক - আচ্ছা ... হ্যাঁ এটি জলরোধী বিবৃতি নয়। তবে সি যখন প্রসঙ্গমুক্ত ব্যাকরণ হিসাবে পার্স করা অসম্ভব, একবারে একজন ব্যক্তি এটি বিশ্লেষণ করার উপায় নিয়ে এসেছিলেন, তবে এটি কঠোর পদক্ষেপ হিসাবে বন্ধ হয়ে যায়। এবং আসল বিষয়টি হল, লোকেরা সহজেই সংযোজনকারীদের সহজেই সাজাতে সক্ষম হওয়ার কারণে এটি তার প্রথম দিনগুলিতে সমৃদ্ধ ছিল , সুতরাং কেএন্ডআর অবশ্যই কিছুটা ভারসাম্য বজায় রেখেছিল। (রিচার্ড গ্যাব্রিয়েলের কুখ্যাত দ্য রাইজ অব "ওয়ার্স ইজ বেটার" তে তিনি
মর্যাদাবান

আমি এটিকে সংশোধন করে খুশি, উপায় দ্বারা - আমি পার্সিং এবং ব্যাকরণ সম্পর্কে এত কিছুই জানি না। আমি historicalতিহাসিক ঘটনা থেকে আরও বেশি অনুমান করছি।
স্পষ্টত

12

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

এটি আজ অবশ্যই হাস্যকর, হার্ড ড্রাইভে অনেক সীমাহীন স্টোরেজ স্পেস সহ। তবে সি এর সাধারণভাবে এমন অদ্ভুত বাক্য গঠন করার কারণ এটি একটি অংশ।


বিশেষভাবে অ্যারে পয়েন্টার সম্পর্কিত, আপনার দ্বিতীয় উদাহরণটি হওয়া উচিত int (*p)[10];(হ্যাঁ সিনট্যাক্সটি খুব বিভ্রান্তিকর)। আমি সম্ভবত এটি "দশটি অ্যারের কাছে পয়েন্টার হিসাবে" পড়ব ... যা কিছুটা অর্থবোধ করে। যদি প্রথম বন্ধনীর জন্য না হয়, সংকলক পরিবর্তে দশ পয়েন্টারের অ্যারে হিসাবে ব্যাখ্যা করবে, যা ঘোষণাকে সম্পূর্ণ ভিন্ন অর্থ দেয়।

যেহেতু অ্যারে পয়েন্টার এবং ফাংশন পয়েন্টার উভয়ই সি-তে যথেষ্ট অস্পষ্ট বাক্য গঠন করে, তাই করার মতো বুদ্ধিমান কাজটি হ'ল অদ্ভুততা দূর করে। সম্ভবত এটির মতো:

অস্পষ্ট উদাহরণ:

int func (int (*arr_ptr)[10])
{
  return 0;
}

int main()
{
  int array[10];
  int (*arr_ptr)[10]  = &array;
  int (*func_ptr)(int(*)[10]) = &func;

  func_ptr(arr_ptr);
}

অস্পষ্ট, সমতুল্য উদাহরণ:

typedef int array_t[10];
typedef int (*funcptr_t)(array_t*);


int func (array_t* arr_ptr)
{
  return 0;
}

int main()
{
  int        array[10];
  array_t*   arr_ptr  = &array; /* non-obscure array pointer */
  funcptr_t  func_ptr = &func;  /* non-obscure function pointer */

  func_ptr(arr_ptr);
}

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


আহ, অবশেষে একটি যুক্তিসঙ্গত উত্তর। :-) আমি নির্দিষ্ট ক্যারেট্যাক্সটি কীভাবে উত্স কোডের আকারটি সঙ্কুচিত করবে সে সম্পর্কে আমি কৌতূহলী, তবে যাইহোক এটি একটি প্রশংসনীয় ধারণা এবং বোধগম্য। ধন্যবাদ। +1
ব্যবহারকারী541686

আমি বলব এটি সোর্স কোডের আকার সম্পর্কে কম এবং সংকলক লেখার বিষয়ে কম ছিল তবে "টাইপডিফ অফ দ্য অদ্ভুততা" এর জন্য অবশ্যই এটি +1। আমার মানসিক স্বাস্থ্যের নাটকীয়ভাবে উন্নতি হয়েছিল যেদিন আমি বুঝতে পারি যে আমি এটি করতে পারি।
অবধি

2
উত্স কোড আকারের জিনিসটিতে [উদ্ধৃতি আবশ্যক]। আমি কখনও এই জাতীয় সীমাবদ্ধতার কথা শুনিনি (যদিও এটি "সবাই জানেন")।
শন ম্যাকমিলান

1
ওয়েল, আমি আইবিএম, ডিসি এবং এক্সেরক্স কিটটিতে সিওবিএল, এসেম্ব্লার, করাল এবং পিএল / 1 এর 70 এর দশকে প্রোগ্রামগুলি কোড করেছিলাম এবং আমি কখনও উত্স কোডের আকার সীমাবদ্ধতা পাইনি। অ্যারের আকার, এক্সিকিউটেবল আকার, প্রোগ্রামের নাম আকার - তবে উত্স কোডের আকারের ক্ষেত্রে সীমাবদ্ধতা।
জেমস অ্যান্ডারসন

1
@ শিয়ান ম্যাকমিলান: আমি মনে করি না যে উত্স কোডের আকারটি একটি সীমাবদ্ধতা ছিল (বিবেচনা করুন যে সেই সময়ে পাস্কালের মতো ভার্বোজ ভাষা বেশ জনপ্রিয় ছিল)। এমনকি যদি এটি হয়ে থাকে তবে আমি মনে করি উত্স কোডটি প্রাক-পার্স করা এবং সংক্ষিপ্ত ওয়ান-বাইট কোডগুলির দ্বারা দীর্ঘ কীওয়ার্ডগুলি প্রতিস্থাপন করা খুব সহজ হত (যেমন কিছু বেসিক দোভাষী দিতেন)। সুতরাং আমি যুক্তিটি খুঁজে পেয়েছি যে "সি সংশ্লেষিত কারণ এটি এমন একটি সময়ে আবিষ্কার করা হয়েছিল যখন কম স্মৃতি পাওয়া যায়" কিছুটা দুর্বল।
জর্জিও

7

এটি বেশ সহজ: এর int *pঅর্থ *pএকটি আন্ত; int a[5]এর মানে a[i]হল একটি অন্তর্নিহিত।

int (*f)(int (*a)[5])

*fএকটি ফাংশন মানে , *aপাঁচটি পূর্ণসংখ্যার অ্যারে, তাই fএকটি ফাংশনটি পাঁচটি পূর্ণসংখ্যার অ্যারে একটি পয়েন্টার গ্রহণ করে এবং পূর্বে ফিরে আসে। যাইহোক, সি-তে এটি কোনও পয়েন্টারকে অ্যারেতে পাস করা কার্যকর নয়।

সি ঘোষণা খুব কমই এই জটিল হয়।

এছাড়াও, আপনি টাইপিডেফগুলি ব্যবহার করে স্পষ্ট করতে পারেন:

typedef int vec5[5];
int (*f)(vec5 *a);

4
দুঃখিত, যদি এটি অভদ্র মনে হয় (তবে আমি এটি বোঝাতে চাইছি না) তবে আপনি মনে করেন আপনি প্রশ্নের পুরো পয়েন্টটি মিস করেছেন ...: \
user541686

2
@ মেহরদাদ: কর্নিগান এবং রিচির মনে কী ছিল তা আমি আপনাকে বলতে পারি না; আমি আপনাকে সিনট্যাক্সের পিছনে যুক্তি দিয়েছিলাম। আমি বেশিরভাগ মানুষের সম্পর্কে জানি না, তবে আমি মনে করি না যে আপনার প্রস্তাবিত বাক্য গঠনটি আরও পরিষ্কার।
কেভিন ক্লাইন

আমি সম্মত - এ জাতীয় জটিল ঘোষণাটি দেখতে অস্বাভাবিক।
কালেব

C- এর নকশা চেয়েও পুরনো ঘোষণা typedef, const, volatile, এবং ঘোষণা মধ্যে কিছু আরম্ভ করার ক্ষমতা। ঘোষণাপত্র সিনট্যাক্সের বিরক্তিকর অস্পষ্টতাগুলির অনেকগুলি (যেমন টাইপের int const *p, *q;সাথে আবদ্ধ হওয়া উচিত constবা ঘোষণাপত্রটি) মূলত ডিজাইন করা ভাষায় উদ্ভূত হতে পারে না। আমি চাই যে ভাষাটি টাইপ এবং ঘোষণাপত্রের মধ্যে একটি কোলন যুক্ত করেছিল, তবে কোয়ালিফায়ার ছাড়াই অন্তর্নির্মিত "সংরক্ষিত-শব্দ" প্রকারগুলি ব্যবহার করার সময় এটি বাদ দিতে দেওয়া হয়েছিল। এর অর্থ int: const *p,*q;এবং int const *: p,*q;স্পষ্ট হত।
সুপারক্যাট

3

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

টাইপ এক্সপ্রেশন পড়ুন

int* (*p)[10];

অন্তর্নিহিত উপাদান পি, একটি পরিবর্তনশীল, তাই

p

অর্থ: পি একটি পরিবর্তনশীল।

ভেরিয়েবলের একটি * থাকার আগে, * অপারেটরটি সর্বদা অভিব্যক্তির আগে প্রকাশিত হয়, সুতরাং,

(*p)

অর্থ: ভেরিয়েবল পি একটি পয়েন্টার। () ব্যতীত [[] ডানদিকে অপারেটরের উচ্চতর অগ্রাধিকার থাকবে, অর্থাৎ

**p[]

হিসাবে পার্স করা হবে

*(*(p[]))

পরবর্তী পদক্ষেপটি []: যেহেতু আর কোনও নেই) (), [] তাই বাইরের * এর চেয়ে উচ্চতর প্রাধান্য রয়েছে, সুতরাং

(*p)[]

অর্থ: (অ্যারেবলের পরিবর্তনশীল পি একটি পয়েন্টার)) তারপরে আমাদের দ্বিতীয়টি রয়েছে:

* (*p)[]

অর্থ: ((চলক পি একটি পয়েন্টার) একটি বিন্যাসে) পয়েন্টার এর

অবশেষে আপনার কাছে ইনট অপারেটর (একটি টাইপের নাম) রয়েছে, যার সর্বনিম্ন নজির রয়েছে:

int* (*p)[]

মানে: ((ভেরিয়েবল পি একটি বিন্যাসে বিন্দু) পয়েন্টার) এর পূর্ণসংখ্যা।

সুতরাং পুরো সিস্টেমটি অপারেটরগুলির সাথে টাইপ এক্সপ্রেশনগুলির উপর ভিত্তি করে এবং প্রতিটি অপারেটরের নিজস্ব প্রাধান্য বিধি রয়েছে। এটি খুব জটিল প্রকারের সংজ্ঞা দিতে দেয়।


0

আপনি ভাবতে শুরু করার সময় এটি এতটা কঠিন নয় এবং সি কখনই খুব সহজ ভাষা ছিল না। এবং এর int*[10]* pচেয়ে int* (*p)[10] K কী ধরণের হবে তা আসলেই সহজ নয়int*[10]* p, k;


2
কে একটি ব্যর্থ কোড পর্যালোচনা হবে,
সংকলকটি

এবং কেন কোড পর্যালোচনা করতে ব্যর্থ হবে?
ডেইনিয়াস

1
কারণ কোডটি অপঠনযোগ্য এবং অভাবনীয়। কোডটি সংশোধন করার জন্য সঠিক নয়, স্পষ্টতই সঠিক এবং রক্ষণাবেক্ষণের পরেও সঠিক থাকার সম্ভাবনা রয়েছে। K কী ধরণের হবে তা আপনাকে জিজ্ঞাসা করতে হবে যে কোডটি এই মৌলিক প্রয়োজনীয়তাগুলি পূরণ করতে ব্যর্থ।
mattnz

1
মূলত একই সারিতে বিভিন্ন ধরণের 3 (এই ক্ষেত্রে) পরিবর্তনশীল ঘোষণা যেমন ইন্ট * পি, ইনট আই [10] এবং ইনট কে। এটা অগ্রহণযোগ্য। একই ধরণের একাধিক ঘোষণা গ্রহণযোগ্য, প্রদত্ত ভেরিয়েবলগুলির কিছু প্রকারের সম্পর্ক থাকে যেমন- প্রস্থ, উচ্চতা, গভীরতা; ইনট * পি ব্যবহার করে অনেক লোকের প্রোগ্রাম মনে রাখবেন, তাই আমি কী 'ইনট * পি, আই;' তে থাকি।
mattnz

1
@ ম্যাটনজ যা বলার চেষ্টা করছে তা হ'ল আপনি যেমন চান তত চালাক হতে পারেন তবে আপনার উদ্দেশ্য যখন পরিষ্কার হয় না এবং / অথবা আপনার কোডটি খারাপ লেখা / অপঠনযোগ্য হয় তখন তা অর্থহীন। এই জাতীয় স্টাফ প্রায়শই ভাঙা কোড এবং সময় নষ্টের ফল দেয়। প্লাস, pointer to intএবং intএমনকি একই ধরণের নয়, তাই এগুলি পৃথকভাবে ঘোষণা করা উচিত। সময়কাল। লোকটির কথা শুনুন। একটি কারণে তার 18 কে রেপ রয়েছে।
ব্র্যাডেন সেরা
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.