সি অ্যারেগুলি কেন তাদের দৈর্ঘ্যের খোঁজ রাখে না?


77

স্পষ্টভাবে একটি অ্যারের সাথে কোনও অ্যারের দৈর্ঘ্য সংরক্ষণ না করার পিছনে যুক্তি কী ছিল C?

আমি যেভাবে দেখি, সেখানে অপ্রতিরোধ্য কারণ আছে তা করার মানক (C89) সমর্থনে কিন্তু খুব অনেক। এই ক্ষেত্রে:

  1. বাফারে দৈর্ঘ্য পাওয়া বাফারকে ছাড়িয়ে নিতে পারে।
  2. একটি জাভা-শৈলী arr.lengthউভয়ই পরিষ্কার এবং প্রোগ্রামারকে intস্ট্যাকের উপর অনেকগুলি বজায় রাখা থেকে বিরত রাখে যদি বেশ কয়েকটি অ্যারে নিয়ে কাজ করে তবে
  3. ফাংশন প্যারামিটারগুলি আরও কমেন্ট হয়।

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

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

আমি কেবল অন্যদিকে ভাবতে পারি যে কোনও দৈর্ঘ্যের ট্র্যাকিং সংকলকগুলি সহজতর করতে পারে নি তবে এটি এত সহজ নয়।

* প্রযুক্তিগতভাবে, কেউ স্বয়ংক্রিয় স্টোরেজ সহ একটি অ্যারের সাথে এক ধরণের পুনরাবৃত্ত ফাংশন লিখতে পারে এবং এটির (খুব বিস্তৃত) ক্ষেত্রে দৈর্ঘ্য সংরক্ষণ করার ফলে কার্যকরভাবে আরও স্থান ব্যবহারের ফলস্বরূপ হতে পারে।


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

3
অন্তর্দৃষ্টিযোগ্য হওয়ার জন্য আপনি পাস্কাল কেন আমার প্রিয় প্রোগ্রামিং ভাষা বিভাগ ২.১ নয় তাও খুঁজে পেতে পারেন।

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

6
আপনার উত্তরের আসল অংশটি ইতিমধ্যে আমার কাছে যেভাবে হবে তার বহুবার উত্তর দেওয়া হয়েছে, তবে আমি একটি ভিন্ন পয়েন্টটি বের করতে পারি: "কেন কোনও malloc()এডের আকারের বহনযোগ্য উপায়ে অনুরোধ করা যাবে না?" এটি এমন একটি জিনিস যা আমাকে কয়েকবার অবাক করে দেয়।
glglgl

5
পুনরায় খুলতে ভোট। কোথাও কোথাও কোনও কারণ রয়েছে, এমনকি যদি এটি কেবল "কেএন্ডআর এটি ভেবে না নেয়"।
টেলাস্টিন

উত্তর:


106

সি অ্যারেগুলি তাদের দৈর্ঘ্যের উপর নজর রাখে, কারণ অ্যারের দৈর্ঘ্য একটি স্থির সম্পত্তি:

int xs[42];  /* a 42-element array */

আপনি সাধারণত এই দৈর্ঘ্যটি জিজ্ঞাসা করতে পারবেন না, তবে আপনার প্রয়োজন হবে না কারণ এটি যাই হোক না কেন স্থির - কেবল XS_LENGTHদৈর্ঘ্যের জন্য একটি ম্যাক্রো ঘোষণা করুন , এবং আপনি শেষ করেছেন।

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

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


13
আমার মনে হয় আপনি বলতে চাইছেন, আমি যদি ভুল না হয়ে থাকি তবে সি সংকলকরা স্থির অ্যারের দৈর্ঘ্যের উপর নজর রাখে। তবে এটি ফাংশনগুলির জন্য ভাল নয় যা কেবল পয়েন্টার পায় poin
ভিএফ 1

25
@ ভিএফ 1 হ্যাঁ তবে গুরুত্বপূর্ণ বিষয় হ'ল অ্যারে এবং পয়েন্টারগুলি সি-তে বিভিন্ন জিনিস । ধরে নিই যে আপনি কোনও সংকলক এক্সটেনশন ব্যবহার করছেন না, আপনি সাধারণত কোনও ফাংশনে কোনও অ্যারে পাস করতে পারবেন না, তবে আপনি একটি পয়েন্টারটি পাস করতে পারেন এবং একটি পয়েন্টারকে সূচি দিতে পারেন যেন এটি অ্যারে হয়। আপনি কার্যকরভাবে অভিযোগ করছেন যে পয়েন্টারগুলির কোনও দৈর্ঘ্য সংযুক্ত নেই। আপনার অভিযোগ করা উচিত যে অ্যারেগুলি ফাংশন আর্গুমেন্ট হিসাবে পাস করা যায় না, বা অ্যারেগুলি সুস্পষ্টভাবে পয়েন্টারগুলিতে অবনমিত হয়।
আমন

37
"আপনি সাধারণত এই দৈর্ঘ্যটি জিজ্ঞাসা করতে পারবেন না" - আসলে আপনি এটি করতে পারেন, এটি আকারের অপারেটর - সাইজেরফ (এক্সএস) 168 ফেরত আসবে বলে ধরে নেওয়া হবে যে চারটি বাইট দীর্ঘ। 42 পেতে, করুন:
মাপ

15
@ টিক্রোসলে এটি কেবল অ্যারে ঘোষণার আওতায় কাজ করে - এক্সকে পরম হিসাবে অন্য কোনও ফাংশনে যাওয়ার চেষ্টা করুন তারপরে দেখুন আকার (এক্সএস) আপনাকে কী প্রদান করবে ...
গুইন ইভান্স

26
@ গুইনএভান্স আবার: পয়েন্টারগুলি অ্যারে নয়। সুতরাং আপনি যদি "অন্য ক্রিয়ায় একটি অ্যারেরকে পরম হিসাবে পাস করেন", আপনি একটি অ্যারে ছাড়িয়ে যাচ্ছেন না তবে পয়েন্টার দিচ্ছেন। sizeof(xs)যেখানে xsঅ্যারে রয়েছে তা অন্য ক্ষেত্রে অন্যরকম কিছু হবে তা দাবি করা সত্যই মিথ্যা, কারণ সি এর নকশা অ্যারেগুলিকে তাদের সুযোগ ছাড়তে দেয় না। তাহলে sizeof(xs)যেখানে xsহয় একটি অ্যারে থেকে ভিন্ন sizeof(xs)যেখানে xsএকটি পয়েন্টার, যে কারণ আপনার হয় কোন আশ্চর্য হিসাবে আসে কমলালেবু সঙ্গে আপেল তুলনা
আমন

38

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

সি এর ইতিহাসের একটি সতর্কতার সাথে পড়লে উপরের বিষয়টিকে আরও বেশি বোঝা পাওয়া যায় তবে এটি তাদের মেশিনের সীমাবদ্ধতার সম্পূর্ণরূপে হয়নি:

তদুপরি, ভাষা (সি) গুরুত্বপূর্ণ ধারণাগুলি বর্ণনা করার জন্য যথেষ্ট শক্তি দেখায়, উদাহরণস্বরূপ, ভেক্টরগুলির দৈর্ঘ্য চলমান সময়ে পরিবর্তিত হয়, কেবল কয়েকটি প্রাথমিক নিয়ম এবং কনভেনশন সহ। ... প্রায় দুটি সমসাময়িক ভাষা আলগল 68 এবং পাস্কাল [জেনসেন 74] এর সাথে সি এর পদ্ধতির তুলনা করা আকর্ষণীয়। আলগোলে 68 তে অ্যারেগুলির নির্দিষ্ট সীমানা রয়েছে, বা `নমনীয়: 'নমনীয় অ্যারে সামঞ্জস্য করার জন্য ভাষা সংজ্ঞা এবং সংকলকগুলিতে উভয়ই যথেষ্ট ব্যবস্থার প্রয়োজন (এবং সমস্ত সংকলক এগুলি পুরোপুরি প্রয়োগ করে না)) মূল পাস্কাল কেবলমাত্র নির্দিষ্ট আকারের ছিল অ্যারে এবং স্ট্রিংগুলি এবং এটি প্রমাণিত করেছিল [কর্নিগান ৮১]।

সি অ্যারেগুলি সহজাতভাবে আরও শক্তিশালী। তাদের মধ্যে সীমাবদ্ধতা প্রোগ্রামার তাদের জন্য কী ব্যবহার করতে পারে তা সীমাবদ্ধ করে। এই জাতীয় বিধিনিষেধ প্রোগ্রামারদের জন্য কার্যকর হতে পারে তবে অগত্যা এটিও সীমাবদ্ধ।


4
এটি প্রায় অনেকটাই মূল প্রশ্ন। অপারেটিং সিস্টেমগুলি লেখার জন্য এটি আকর্ষণীয় করে তোলার অংশ হিসাবে প্রোগ্রামারটি কী করছে তা যাচাই করার সময় যখন সিটি ইচ্ছাকৃতভাবে "হালকা স্পর্শ" রাখা হচ্ছিল তা এবং।
ClickRick

5
দুর্দান্ত লিঙ্ক, তারা ডিলিমিটারটি ব্যবহার করার জন্য স্ট্রিংয়ের দৈর্ঘ্যগুলি স্পষ্টভাবে পরিবর্তিত to avoid the limitation on the length of a string caused by holding the count in an 8- or 9-bit slot, and partly because maintaining the count seemed, in our experience, less convenient than using a terminatorকরেছে
এটির

5
অসমাপ্ত অ্যারে এছাড়াও ফিট সি বেয়ার মেটাল পদ্ধতির সঙ্গে মনে রাখবেন যে কে & R এর সি বই একটি ভাষা টিউটোরিয়াল, রেফারেন্স এবং স্ট্যান্ডার্ড কল একটি তালিকা সঙ্গে কম 300 পৃষ্ঠাগুলি হয়। আমার ও'রিলি রেজেক্স বইটি কে ও আর সি থেকে প্রায় দ্বিগুণ দীর্ঘ
মাইকেল শপসিন

22

সেদিন ফিরে যখন সি তৈরি হয়েছিল, এবং প্রতিটি স্ট্রিংয়ের জন্য অতিরিক্ত 4 বাইট স্পেস যতই সংক্ষিপ্ত পরিমাণই নষ্ট হত না কেন !

আরও একটি সমস্যা আছে - মনে রাখবেন যে সি বস্তু-ভিত্তিক নয়, সুতরাং আপনি যদি সমস্ত স্ট্রিং দৈর্ঘ্য-উপসর্গ করেন তবে এটি একটি সংকলক অন্তর্নিহিত ধরণের হিসাবে সংজ্ঞায়িত করতে হবে char*। যদি এটি কোনও বিশেষ ধরণের হয় তবে আপনি একটি স্ট্রিংকে একটি ধ্রুব স্ট্রিংয়ের সাথে তুলনা করতে সক্ষম হবেন না, যেমন:

String x = "hello";
if (strcmp(x, "hello") == 0) 
  exit;

স্ট্যাটিক স্ট্রিংটিকে একটি স্ট্রিংয়ে রূপান্তর করতে বিশেষ সংকলক বিশদ থাকতে হবে বা দৈর্ঘ্যের উপসর্গটি অ্যাকাউন্টে নিতে বিভিন্ন স্ট্রিং ফাংশন থাকতে হবে।

আমি শেষ পর্যন্ত যদিও মনে করি, তারা কেবল পাস্কাল বলার অপেক্ষা পৃথক দৈর্ঘ্য-উপসর্গটি পছন্দ করেনি।


10
বাউন্ড চেক করতেও সময় লাগে। আজকের পদগুলিতে তুচ্ছ, তবে লোকে যখন প্রায় 4 বাইট যত্ন নিয়েছিল তখন কিছু লোক তার প্রতি মনোযোগ দিয়েছে।
স্টিভেন বার্নাপ

18
@ স্টিভেন বার্নাপ: আপনি যদি এমন কোনও অভ্যন্তরীণ লুপতে থাকেন যা 200 এমবি চিত্রের প্রতিটি পিক্সেলের উপরে চলে যায় তবে এটি আজও তুচ্ছ নয়। সাধারণভাবে, আপনি সি লিখছেন যদি আপনি দ্রুত যেতে চান , এবং আপনার forলুপটি ইতিমধ্যে সীমানাগুলি সম্মানের জন্য স্থাপন করা হয়েছিল তখন প্রতিটি পুনরাবৃত্তিতে একটি অকেজো বাউন্ড চেকের সময় নষ্ট করতে চান না ।
মাত্তেও ইটালিয়া

4
@ ভিএফ 1 "দিনের আগের দিন" এটি দুটি বাইট হতে পারে (ডিসি পিডিপি / 11 কেউ?)
রিক

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

3
বিসিপিএলে দৈর্ঘ্য গণনা করা যুক্তি ছিল তা বিবেচনা করে এটি আসলে একটি বরং দুর্বল যুক্তি। ঠিক তেমনি পাস্কাল যদিও এটি 1 শব্দের মধ্যে সীমাবদ্ধ ছিল তাই কেবল 8 বা 9 টি বিট ছিল যা কিছুটা সীমাবদ্ধ ছিল (এটি স্ট্রিংগুলির অংশগুলি ভাগ করে নেওয়ার সম্ভাবনাও বঞ্চিত করে, যদিও সেই সময়ের জন্য এটি অপ্টিমাইজেশন সম্ভবত বেশ উন্নত ছিল)। এবং অ্যারে দ্বারা অনুসরণ করা একটি দৈর্ঘ্য সহ স্ট্রিংটিকে স্ট্রাকচার হিসাবে ঘোষণা করার জন্য সত্যিকারের বিশেষ সংকলক সহায়তার প্রয়োজন হবে না ..
ভু

11

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


6
"ডিজাইনটি আলাদা হবে" ডিজাইনের আলাদা হওয়ার কোনও কারণ নয়।
ভিএফ 1

7
@ ভিএফ 1: আপনি কি কখনও স্ট্যান্ডার্ড পাস্কেলে প্রোগ্রাম করেছেন? অ্যারের সাথে যুক্তিসঙ্গতভাবে নমনীয় হওয়ার সিটির দক্ষতা ছিল সমাবেশের তুলনায় বিশাল উন্নতি (যা কোনও সুরক্ষা নেই) এবং টাইপসেফ ভাষার প্রথম প্রজন্ম (ওভারকিল টাইপস্যাফটি, সঠিক অ্যারের সীমানা সহ)
এমসাল্টারস 28:30 '

5
অ্যারে টুকরো টুকরো করার এই ক্ষমতাটি সত্যই C89 ডিজাইনের জন্য একটি বিশাল যুক্তি।

ওল্ড স্কুল ফোরট্রান হ্যাকাররাও এই সম্পত্তিটির [dk] ভাল ব্যবহার করতে পারে (তবে এটি ফোরট্রানের একটি অ্যারেতে স্লাইসটি পাস করতে হবে)। প্রোগ্রাম বা ডিবাগের জন্য বিভ্রান্তিকর এবং বেদনাদায়ক, তবে কাজ করার সময় দ্রুত এবং মার্জিত।
dmckee

3
একটি আকর্ষণীয় নকশার বিকল্প রয়েছে যা স্লাইসিংয়ের অনুমতি দেয়: অ্যারেগুলির পাশাপাশি দৈর্ঘ্যটি সংরক্ষণ করবেন না। কোনও অ্যারেতে কোনও পয়েন্টারের জন্য, পয়েন্টারটির সাথে দৈর্ঘ্যটি সঞ্চয় করুন। (যখন আপনার কেবলমাত্র একটি আসল সি অ্যারে রয়েছে, আকারটি একটি সংকলন সময় ধ্রুবক এবং সংকলকটির জন্য উপলভ্য)) এটি আরও বেশি জায়গা নেয়, তবে দৈর্ঘ্য বজায় রেখে টুকরো টুকরো করে দেয়। মরিচা &[T]উদাহরণস্বরূপ, প্রকারের জন্য এটি করে ।

8

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

void ClearTwoElements(int *ptr)
{
  ptr[-2] = 0;
  ptr[2] = 0;
}
void blah(void)
{
  static int foo[10] = {1,2,3,4,5,6,7,8,9,10};
  ClearTwoElements(foo+2);
  ClearTwoElements(foo+7);
  ClearTwoElements(foo+1);
  ClearTwoElements(foo+8);
}

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

void ClearTwoElements(int *ptr)
{
  int* array_end = ARRAY_END(ptr);
  if ((array_end - ARRAY_BASE(ptr)) < 10 ||
      (ARRAY_BASE(ptr)+4) <= ADDRESS(ptr) ||          
      (array_end - 4) < ADDRESS(ptr)))
    trap();
  *(ADDRESS(ptr) - 4) = 0;
  *(ADDRESS(ptr) + 4) = 0;
}

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

void ClearTwoElements(int arr[], int index)
{
  arr[index-2] = 0;
  arr[index+2] = 0;
}
void blah(void)
{
  static int foo[10] = {1,2,3,4,5,6,7,8,9,10};
  ClearTwoElements(foo,2);
  ClearTwoElements(foo,7);
  ClearTwoElements(foo,1);
  ClearTwoElements(foo,8);
}

একটি ধরণের ধারণা যা কোনও জিনিসের সাথে কিছু মিলিয়ে কোনও জিনিসকে কোনও কিছুকে চিহ্নিত করার জন্য কোনও অংশকে চিহ্নিত করতে পারে এটি ভাল। সি-স্টাইল পয়েন্টারটি দ্রুততর হয়, তবে যদি এটি বৈধতা সম্পাদন করার প্রয়োজন হয় না।


অ্যারেগুলিতে রানটাইমের আকার থাকলে পয়েন্টার থেকে অ্যারে পয়েন্টার থেকে অ্যারের উপাদানের কাছে মৌলিকভাবে আলাদা হবে। উত্তরোত্তর সরাসরি কোনও ক্ষেত্রে সরাসরি রূপান্তরিত নাও হতে পারে (নতুন অ্যারে তৈরি না করে)। []পয়েন্টারগুলির জন্য সিনট্যাক্স এখনও বিদ্যমান থাকতে পারে তবে এই অনুমান "বাস্তব" অ্যারেগুলির চেয়ে আলাদা হবে এবং আপনি যে সমস্যাটি বর্ণনা করেছেন তা সম্ভবত উপস্থিত না থাকায়।
হাইড

@ হাইড: প্রশ্নটি হল যে গাণিতিকগুলিকে সেই পয়েন্টারে অনুমতি দেওয়া উচিত যাঁর অবজেক্টের বেস ঠিকানাটি অজানা। এছাড়াও, আমি আরেকটি অসুবিধা ভুলে গিয়েছি: কাঠামোর মধ্যে অ্যারেগুলি। এ সম্পর্কে চিন্তাভাবনা করে, আমি নিশ্চিত নই যে এখানে কোনও পয়েন্টার টাইপ রয়েছে যা কাঠামোর মধ্যে সঞ্চিত অ্যারেতে নির্দেশ করতে পারে, প্রতিটি পয়েন্টারকে কেবল পয়েন্টারের নিজের ঠিকানাই অন্তর্ভুক্ত করার প্রয়োজন নেই, তবে উপরের এবং নিম্নতর আইনীও রয়েছে ব্যাপ্তি এটি অ্যাক্সেস করতে পারেন।
সুপারক্যাট

ইন্টারসেটিং পয়েন্ট। আমি মনে করি এটি এখনও amon এর উত্তর হ্রাস, যদিও।
ভিএফ 1

প্রশ্ন অ্যারে সম্পর্কে জিজ্ঞাসা করে। পয়েন্টার হ'ল মেমরি ঠিকানা এবং প্রশ্নটির ভিত্তিতে কোনও পরিবর্তন হয় না, যতক্ষণ না উদ্দেশ্যটি বোঝে। অ্যারেগুলি দৈর্ঘ্য পাবে, পয়েন্টারগুলি অপরিবর্তিত থাকবে (পয়েন্টার থেকে অ্যারে ব্যতীত নতুন, স্বতন্ত্র, অনন্য প্রকারের দরকার হবে, যেমন স্ট্রাকচারে পয়েন্টারের মতো)।
হাইড

@ হাইড: যদি কেউ ভাষার শব্দার্থবিদ্যার যথেষ্ট পরিবর্তন করে তবে অ্যারেগুলির সাথে একটি যুক্ত দৈর্ঘ্য অন্তর্ভুক্ত থাকতে পারে, যদিও কাঠামোর মধ্যে থাকা অ্যারেগুলি কিছু অসুবিধা সৃষ্টি করতে পারে। শব্দার্থক যেমন রয়েছে তেমনি অ্যারে বাউন্ডস-চেকিং কেবল তখনই কার্যকর হবে যদি সেই একই চেকিং অ্যারে উপাদানগুলিতে পয়েন্টারগুলিতে প্রয়োগ করা হয়।
সুপারক্যাট

7

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

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


3
সি এর বিবর্তনের সাথে সাথে এতটা "ডিজাইন" করা হয়নি। মূলত, একটি ঘোষণার জন্য পাঁচ-আইটেম অ্যারে হিসাবে int f[5];তৈরি fকরা হবে না ; পরিবর্তে, এটি সমতুল্য ছিল int CANT_ACCESS_BY_NAME[5]; int *f = CANT_ACCESS_BY_NAME;। সংকলক ব্যতীত পূর্বের ঘোষণাপত্রটি সত্যই "অ্যারে সময়" বোঝার জন্য প্রক্রিয়া করা যেত; এটি কেবল স্থান বরাদ্দের জন্য একটি এসেম্বলারের নির্দেশকে আউটপুট করতে হয়েছিল এবং তারপরে এটি ভুলে যেতে পারে যে fঅ্যারের সাথে কখনও কোনও সম্পর্ক ছিল। অ্যারে ধরণের অসঙ্গতিপূর্ণ আচরণগুলি এ থেকে উদ্ভূত হয়।
ক্যাট

1
দেখা যাচ্ছে যে কোনও প্রোগ্রামার জানে না যে তারা সি প্রয়োজনীয় ডিগ্রীতে কী করছে।
কোডসইনচাওস

7

সংক্ষিপ্ত উত্তর:

সি একটি নিম্ন-স্তরের প্রোগ্রামিং ভাষা হওয়ায় এটি আপনাকে নিজেরাই এই বিষয়গুলির যত্ন নেওয়ার প্রত্যাশা করে, তবে আপনি কীভাবে এটি বাস্তবায়ন করেন তার মধ্যে এটি আরও বেশি নমনীয়তা যুক্ত করে।

সিটিতে একটি অ্যারের একটি সংকলন-সময় ধারণা রয়েছে যা দৈর্ঘ্যের সাহায্যে সূচনা করা হয় তবে রানটাইমের সময় পুরো জিনিসটি কেবল ডেটা শুরু করার জন্য একক পয়েন্টার হিসাবে সঞ্চিত থাকে। যদি আপনি অ্যারের পাশাপাশি কোনও ফাংশনে অ্যারের দৈর্ঘ্যটি পাস করতে চান তবে আপনি নিজেই করুন:

retval = my_func(my_array, my_array_length);

অথবা আপনি একটি পয়েন্টার এবং দৈর্ঘ্য, বা অন্য কোনও সমাধান সহ একটি কাঠামো ব্যবহার করতে পারেন।

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

স্পষ্টত অসুবিধাটি হ'ল বিন্যাস হিসাবে বিন্যাসের চারপাশে কোনও অন্তর্নিহিত সীমানা পরীক্ষা না করে আপনি কিছু বিপজ্জনক কোড তৈরি করতে পারেন তবে এটি নিম্ন স্তরের / সিস্টেমের ভাষা এবং তারা যে বাণিজ্য দেয় তা প্রকৃতি।


1
+1 "এবং আপনি যে কোডটি লিখছেন তা যদি অ্যারের দৈর্ঘ্যটি ইতিমধ্যে জেনে থাকে তবে আপনার ভেরিয়েবল হিসাবে মোটামুটি দৈর্ঘ্যটি পাস করার দরকার নেই।"
40 皞

যদি কেবলমাত্র পয়েন্টার + দৈর্ঘ্যের কাঠামোটি ভাষা এবং স্ট্যান্ডার্ড লাইব্রেরিতে বেক করা হত। এতগুলি নিরাপত্তা হোল এড়ানো যেত।
কোডসইনচাওস

তাহলে এটি আসলে সি হবে না be এমন অন্যান্য ভাষা রয়েছে যা এটি করে। সি আপনাকে নিম্ন স্তরের করে তোলে।
থোমস্রুটার

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

5

অতিরিক্ত সঞ্চয়স্থানের সমস্যাটি একটি সমস্যা, তবে আমার মতে একটি ছোটখাটো। সর্বোপরি, বেশিরভাগ সময় আপনাকে যেভাবেই দৈর্ঘ্যটি ট্র্যাক করতে হবে, যদিও অ্যামন একটি ভাল পয়েন্ট দিয়েছে যে এটি প্রায়শই স্ট্যাটিকভাবে ট্র্যাক করা যায়।

একটি বড় সমস্যা হ'ল দৈর্ঘ্যটি কোথায় সংরক্ষণ করতে হবে এবং কতক্ষণ এটি করা উচিত। এমন একটি জায়গা নেই যা সমস্ত পরিস্থিতিতে কাজ করে। আপনি হয়ত বলতে পারেন ডেটার ঠিক আগে মেমোরিতে দৈর্ঘ্য সংরক্ষণ করুন। অ্যারে যদি মেমরিটির দিকে ইঙ্গিত না করে তবে একটি ইউআরএফ বাফারের মতো কিছু করে?

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


1
You might say just store the length in the memory just before the data. What if the array isn't pointing to memory, but something like a UART buffer?আপনি দয়া করে এটি আরও কিছুটা ব্যাখ্যা করতে পারেন? এছাড়াও যে খুব ঘন ঘন ঘটতে পারে বা এটি একটি বিরল ঘটনা?
মাহদি

যদি আমি এটি ডিজাইন করে থাকি তবে একটি ফাংশন আর্গুমেন্ট হিসাবে লিখিত T[]না হয়ে সমতুল্য হবে না T*বরং ফাংশনে পয়েন্টার এবং আকারের একটি টুপল পাস করে। নির্দিষ্ট আকারের অ্যারেগুলি সি হিসাবে করা পয়েন্টারগুলিকে ক্ষয় করার পরিবর্তে এ জাতীয় অ্যারের ফালিগুলিতে ক্ষয় করতে পারে এই পদ্ধতির মূল সুবিধাটি এটি নয় যে এটি নিজেই নিরাপদ, তবে এটি একটি কনভেনশন যার ভিত্তিতে স্ট্যান্ডার্ড লাইব্রেরি সহ সমস্ত কিছু সম্ভব নির্মাণ।
কোডসইনচাওস

1

সি ভাষার বিকাশ থেকে :

কাঠামোগুলি, মনে হয়েছিল, মেশিনে মেমরির জন্য একটি স্বজ্ঞাত উপায়ে মানচিত্র তৈরি করা উচিত, তবে অ্যারেযুক্ত কাঠামোর মধ্যে অ্যারের বেসটি সহ পয়েন্টারটি স্ট্যাশ করার কোনও ভাল জায়গা ছিল না বা এটি ব্যবস্থা করার কোনও সুবিধাজনক উপায় ছিল না arrange সক্রিয়া। উদাহরণস্বরূপ, প্রাথমিক ইউনিক্স সিস্টেমের ডিরেক্টরি এন্ট্রিগুলি সি হিসাবে বর্ণিত হতে পারে
struct {
    int inumber;
    char    name[14];
};
আমি কাঠামোটি কেবল একটি বিমূর্ত বস্তুর বৈশিষ্ট্যই নয়, বিটগুলির একটি সংকলনও বর্ণনা করতে চেয়েছি যা ডিরেক্টরি থেকে পড়তে পারে wanted কম্পাইলারটি nameশব্দার্থকেরা যে নির্দেশকের কাছে পয়েন্টারটি লুকিয়ে রাখতে পারে ? এমনকি যদি কাঠামোগুলিকে আরও বিমূর্তভাবে চিন্তা করা হত এবং পয়েন্টারগুলির জন্য স্থানটি কোনওভাবে লুকানো যেতে পারে তবে কোনও জটিল বিষয় বরাদ্দ করার সময় আমি কীভাবে এই পয়েন্টারগুলিকে সঠিকভাবে শুরু করার প্রযুক্তিগত সমস্যাটি পরিচালনা করতে পারি, সম্ভবত এমন কোনও একটি যা নির্দিষ্ট কাঠামোকে স্বেচ্ছাসেবী গভীরতায় স্ট্রাকচারযুক্ত অ্যারে যুক্ত করে থাকে?

সমাধানটি টাইপলেস বিসিপিএল এবং টাইপ করা সি এর মধ্যে বিবর্তনমূলক শৃঙ্খলে গুরুত্বপূর্ণ লাফিয়ে দাঁড় করায় এটি স্টোরেজে পয়েন্টারটির বস্তুগতকরণকে বাদ দেয় এবং পরিবর্তে অ্যারের নামটি যখন একটি অভিব্যক্তিতে উল্লেখ করা হয় তখন পয়েন্টারটির সৃষ্টি করে। আজকের সি-তে টিকে থাকা এই নিয়মটি হ'ল অ্যারে প্রকারের মানগুলি রূপান্তরিত হয়, যখন সেগুলি অভিব্যক্তিগুলিতে উপস্থিত হয়, অ্যারে তৈরির প্রথম বস্তুর পয়েন্টারে পরিণত হয়।

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

এছাড়াও, বহুমাত্রিক অ্যারেগুলি সম্পর্কে ভাবুন; যেখানে আপনি প্রতিটি মাত্রার জন্য দৈর্ঘ্যের মেটাডেটা এমনভাবে সঞ্চয় করবেন যেখানে আপনি এখনও কোনও কিছু দিয়ে অ্যারে পেরিয়ে যেতে পারেন

T *p = &a[0][0];

for ( size_t i = 0; i < rows; i++ )
  for ( size_t j = 0; j < cols; j++ )
    do_something_with( *p++ );

-2

প্রশ্নটি ধরে নিয়েছে যে সি তে অ্যারে রয়েছে are যে জিনিসগুলিকে অ্যারে বলা হয় তা হ'ল ডেটা এবং পয়েন্টার গাণিতিকের ক্রমাগত ক্রমগুলির ক্রিয়াকলাপের জন্য একটি সিনট্যাকটিক চিনি।

নিম্নলিখিত কোডটি সিআরসি থেকে ডিএসটি-তে কিছু তথ্য অনুলিপি আকারের অংশগুলিতে অনুলিপি করে যা এটি জানে না যে এটি আসলে চরিত্রের স্ট্রিং।

char src[] = "Hello, world";
char dst[1024];
int *my_array = src; /* What? Compiler warning, but the code is valid. */
int *other_array = dst;
int i;
for (i = 0; i <= sizeof(src)/sizeof(int); i++)
    other_array[i] = my_array[i]; /* Oh well, we've copied some extra bytes */
printf("%s\n", dst);

সিটিকে এত সরল করে কেন এটিতে সঠিক অ্যারে নেই? আমি এই নতুন প্রশ্নের সঠিক উত্তর জানি না। তবে কিছু লোক প্রায়শই বলে থাকেন যে সি কেবলমাত্র (কিছুটা) বেশি পঠনযোগ্য এবং পোর্টেবল এসেমব্লার।


2
আমি মনে করি না আপনি প্রশ্নের উত্তর দিয়েছেন।
রবার্ট হার্ভে

2
আপনি যা বলেছেন তা সত্য, তবে জিজ্ঞাসা করা ব্যক্তিটি কেন এটি হল তা জানতে চায় ।

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

8
অন্য কোন কনস্ট্রাক্ট দিয়ে আপনি কীভাবে একই বাইনারি তৈরি করতে পারবেন না তা বিবেচনা করে সি এর কোনও অ্যারে নেই বলা ভুল (ভাল, কমপক্ষে যদি আপনি অ্যারের আকারগুলি নির্ধারণের জন্য # নির্দিষ্টকরণের ব্যবহার বিবেচনা করেন) তবে তা নয়। সি অ্যারেগুলির হয় "তথ্য ক্রমাগত সিকোয়েন্স", এটি সম্পর্কে শর্করাবৎ কিছুই নেই। পয়েন্টারগুলি যেমন অ্যারে ছিল তাদের ব্যবহার হ'ল এখানে সিনট্যাকটিক চিনি (সুস্পষ্ট পয়েন্টার গাণিতিকের পরিবর্তে), নিজে অ্যারে নয়।
হাইড

2
হ্যাঁ, এই কোড বিবেচনা করুন: struct Foo { int arr[10]; }arrএকটি অ্যারে, পয়েন্টার নয়।
স্টিভেন বার্নাপ 21
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.