c - সি তে অ্যারে ইনিশিয়ালাইজেশন সম্পর্কে বিভ্রান্তি




arrays initialization (5)

আমি বুঝতে পারি না, কেন a[0] 0 পরিবর্তে 1 মুদ্রণ করে?

সম্ভবত a[2]=1 প্রথমে a[2] আরম্ভ করে এবং অভিব্যক্তির ফলাফলটি a[0] আরম্ভ করার জন্য ব্যবহৃত হয়।

N2176 (সি 17 খসড়া) থেকে:

6.7.9 সূচনা

  1. সূচনা তালিকা প্রকাশের মূল্যায়নগুলি অনির্দিষ্টকালের জন্য একে অপরের প্রতি শ্রদ্ধার সাথে ক্রমযুক্ত এবং এভাবে কোনও পার্শ্বপ্রতিক্রিয়ার ক্রমটি অনির্ধারিত। 154)

সুতরাং মনে হয় যে আউটপুট 1 0 0 0 0 এছাড়াও সম্ভব ছিল।

উপসংহার: প্রারম্ভিক লেখাগুলি লিখবেন না যা ফ্লাইতে প্রারম্ভিক পরিবর্তনশীলকে সংশোধন করে।

সি ভাষায়, যদি এর মতো একটি অ্যারে শুরু করে:

int a[5] = {1,2};

তারপরে অ্যারের সমস্ত উপাদান যা স্পষ্টভাবে আরম্ভ করা হয়নি তা জিরো দিয়ে সুস্পষ্টভাবে আরম্ভ করা হবে।

তবে, যদি আমি এর মতো একটি অ্যারে শুরু করি:

int a[5]={a[2]=1};

printf("%d %d %d %d %d\n", a[0], a[1],a[2], a[3], a[4]);

আউটপুট:

1 0 1 0 0

আমি বুঝতে পারি না, কেন a[0] 0 পরিবর্তে 1 মুদ্রণ করে? এটা কি অপরিবর্তিত আচরণ?

দ্রষ্টব্য: এই প্রশ্নটি একটি সাক্ষাত্কারে জিজ্ঞাসা করা হয়েছিল।


অ্যাসাইনমেন্ট a[2]= 1 হল একটি অভিব্যক্তি যার মান 1 এবং আপনি মূলত লিখেছেন int a[5]= { 1 }; (পার্শ্ব প্রতিক্রিয়া সহ যে a[2] কেও 1 বরাদ্দ করা হয়েছে)।


আমি বিশ্বাস করি, এটি int a[5]={ a[2]=1 }; কোনও প্রোগ্রামার তাকে / তার নিজের পায়ে গুলি করার জন্য এটি একটি উত্তম উদাহরণ।

আমি ভেবে প্রলুব্ধ হতে পারি যে আপনি যা বোঝাতে চেয়েছিলেন তা হ'ল int a[5]={ [2]=1 }; যা কোনও সি 99 মনোনীত ইনিশিয়ালাইজার সেটিং উপাদান 2 থেকে 1 এবং বাকী শূন্য হবে।

বিরল ক্ষেত্রে যে আপনি সত্যিকার অর্থেই int a[5]={ 1 }; a[2]=1; int a[5]={ 1 }; a[2]=1; , তবে এটি লেখার মজার উপায় হবে। যাইহোক, আপনার কোডটি এটাই ফোটায়, যদিও কিছু এখানে উল্লেখ করেছে যে a[2] এ লেখাটি কার্যকর করার সময় এটি সঠিকভাবে সংজ্ঞায়িত হয়নি। এখানে সমস্যাটি হ'ল a[2]=1 কোনও নির্ধারিত আরম্ভকারী নয় বরং একটি সরল অ্যাসাইনমেন্ট যা নিজেই মান 1 করে।


আমি মনে করি সি 11 মানকটি এই আচরণটি কভার করে এবং বলে যে ফলাফল অনির্ধারিত , এবং আমি মনে করি না C18 এই ক্ষেত্রে কোনও প্রাসঙ্গিক পরিবর্তন করেছে।

মানক ভাষাটি বিশ্লেষণ করা সহজ নয়। স্ট্যান্ডার্ডটির প্রাসঙ্গিক বিভাগটি Initial6.7.9 ইনিশিয়ালাইজেশন । বাক্য গঠনটি নথিভুক্ত করা হয়:

initializer:
assignment-expression
{ initializer-list }
{ initializer-list , }
initializer-list:
designation opt initializer
initializer-list , designation opt initializer
designation:
designator-list =
designator-list:
designator
designator-list designator
designator:
[ constant-expression ]
. identifier

নোট করুন যে পদগুলির মধ্যে একটি হ'ল অ্যাসাইনমেন্ট-এক্সপ্রেশন এবং a[2] = 1 যেহেতু নির্দ্বিধায় একটি অ্যাসাইনমেন্ট এক্সপ্রেশন, তাই এটি অ স্থির সময়কাল সহ অ্যারেগুলির জন্য আরম্ভকারীদের ভিতরে অনুমোদিত হয়:

§4 স্ট্যাটিক বা থ্রেড স্টোরেজ সময়কাল এমন কোনও অবজেক্টের জন্য ইনিশিয়ালাইজারের সমস্ত এক্সপ্রেশন হ'ল স্থির এক্সপ্রেশন বা স্ট্রিং লিটারাল।

মূল অনুচ্ছেদের মধ্যে একটি:

§19 সূচনাটি আরম্ভকারী তালিকার ক্রমে সংঘটিত হবে, প্রতিটি ইনিশিয়ালাইজার একই সাবোবজেক্টের জন্য পূর্বের তালিকাভুক্ত আরম্ভকারীকে ওভাররাইড করে নির্দিষ্ট সাবোবজেক্টের জন্য সরবরাহ করা হয়; 151) সমস্ত সাবওজেক্টস যা স্পষ্টভাবে আরম্ভ করা হয়নি তা স্পষ্টভাবে আরম্ভ করা হবে স্থিতিশীল স্টোরেজ সময়কালের অবজেক্টগুলির মতোই।

151) সাবোবজেক্টের জন্য কোনও আরম্ভকারী যা ওভাররাইড হয়ে গেছে এবং তাই আরম্ভ করতে ব্যবহৃত হয়নি যে সাবোবজেক্টটি মোটেও মূল্যায়ন করা যাবে না।

এবং অন্য কী অনুচ্ছেদে হ'ল:

§ 23 সূচনা তালিকা প্রকাশের মূল্যায়নগুলি অনির্দিষ্টকালের জন্য একে অপরের প্রতি সম্মানযুক্ত এবং এভাবে কোনও পার্শ্বপ্রতিক্রিয়াগুলি ক্রমটি অনির্ধারিত। 152)

152) বিশেষত, মূল্যায়ন আদেশ সাবোবজেক্ট আরম্ভের ক্রমের মতো হওয়া উচিত নয়।

আমি মোটামুটি নিশ্চিত যে অনুচ্ছেদ § 23 ইঙ্গিত দেয় যে প্রশ্নটিতে চিহ্নিতকরণ:

int a[5] = { a[2] = 1 };

অনির্দিষ্ট আচরণ বাড়ে। a[2] এ নিয়োগটি একটি পার্শ্ব-প্রতিক্রিয়া, এবং অভিব্যক্তিগুলির মূল্যায়ন ক্রমটি একে অপরের প্রতি শ্রদ্ধার সাথে অনিচ্ছাকৃতভাবে ক্রমযুক্ত। ফলস্বরূপ, আমি মনে করি না যে স্ট্যান্ডার্ডের কাছে আবেদন করার এবং দাবি করার কোনও উপায় আছে যে কোনও নির্দিষ্ট সংকলক এটি সঠিকভাবে বা ভুলভাবে পরিচালনা করছে।


ধাঁধার জন্য আমি একটি সংক্ষিপ্ত এবং সহজ উত্তর দেওয়ার চেষ্টা করি: int a[5] = { a[2] = 1 };

  1. প্রথমে a[2] = 1 সেট করা আছে। এর অর্থ অ্যারে বলেছেন: 0 0 1 0 0
  2. তবে দেখুন, আপনি এটি { } বন্ধনীগুলিতে করেছিলেন যা ক্রমানুসারে অ্যারে শুরু করার জন্য ব্যবহৃত হয়, এটি প্রথম মান নেয় (যা 1 ) এবং এটি সেট করে a[0] । এটি যেন int a[5] = { a[2] }; থেকে যাবে, যেখানে আমরা ইতিমধ্যে a[2] = 1 পেয়েছি। ফলাফল অ্যারে এখন: 1 0 1 0 0

আর একটি উদাহরণ: int a[6] = { a[3] = 1, a[4] = 2, a[5] = 3 }; - যদিও আদেশটি কিছুটা নির্বিচারে, ধরে নিলেও এটি বাম থেকে ডানে চলে গেছে, এই 6 টি পদক্ষেপে এটি যাবে:

0 0 0 1 0 0
1 0 0 1 0 0
1 0 0 1 2 0
1 2 0 1 2 0
1 2 0 1 2 3
1 2 3 1 2 3




language-lawyer