লুপের ভিতরে ভেরিয়েবলগুলি ঘোষণা করা, ভাল অনুশীলন বা খারাপ অনুশীলন?


264

প্রশ্ন # 1: লুপের অভ্যন্তরে একটি ভেরিয়েবল ঘোষণা করা একটি ভাল অভ্যাস বা খারাপ অনুশীলন?

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

উদাহরণ:

for(int counter = 0; counter <= 10; counter++)
{
   string someString = "testing";

   cout << someString;
}

প্রশ্ন # 2: বেশিরভাগ সংকলকরা কি বুঝতে পারে যে ভেরিয়েবলটি ইতিমধ্যে ঘোষিত হয়েছে এবং কেবলমাত্র সেই অংশটি এড়িয়ে গেছে, বা এটি আসলে কি প্রতিটি বারের জন্য মেমরির জন্য একটি স্পট তৈরি করে?


29
প্রোফাইলিং অন্যথায় না বললে এগুলি তাদের ব্যবহারের কাছে রাখুন।
মাকিং হাঁস

1
এখানে কিছু অনুরূপ প্রশ্ন হল: stackoverflow.com/questions/982963/... stackoverflow.com/questions/407255/...
drnewman

3
@ ড্রনেউম্যান আমি এই থ্রেডগুলি পড়েছি, তবে তারা আমার প্রশ্নের উত্তর দেয়নি। আমি বুঝতে পারি লুপের অভ্যন্তরে ভেরিয়েবলগুলি ঘোষিত করে কাজ করে। আমি ভাবছি এটি করা ভাল অভ্যাস কিনা বা এটি এড়ানো কিছু আছে কিনা।
জেরামিরআর

উত্তর:


348

এটি দুর্দান্ত অনুশীলন।

লুপের ভিতরে ভেরিয়েবল তৈরি করে, আপনি নিশ্চিত করেন যে তাদের সুযোগটি লুপের অভ্যন্তরে সীমাবদ্ধ। এটি লুপের বাইরে রেফারেন্স করা বা কল করা যায় না।

এই পথে:

  • যদি ভেরিয়েবলের নামটি কিছুটা "জেনেরিক" হয় (যেমন "আই") হয় তবে আপনার কোডের পরে কোথাও এটি একই নামের অন্য ভেরিয়েবলের সাথে মিশ্রিত করার কোনও ঝুঁকি নেই (জিসিসিতে -Wshadowসতর্কতা নির্দেশ ব্যবহার করে প্রশমিতও করা যেতে পারে )

  • সংকলক জানে যে ভেরিয়েবল স্কোপটি লুপের মধ্যেই সীমাবদ্ধ থাকে এবং ভেরিয়েবলটি অন্য কোথাও ভুল করে রেফারেন্স করা হলে সঠিক ত্রুটি বার্তা জারি করবে।

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

সংক্ষেপে, আপনি এটি করা ঠিক।

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

{
    int i, retainValue;
    for (i=0; i<N; i++)
    {
       int tmpValue;
       /* tmpValue is uninitialized */
       /* retainValue still has its previous value from previous loop */

       /* Do some stuff here */
    }
    /* Here, retainValue is still valid; tmpValue no longer */
}

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

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

এটি কোনও if(){...}ব্লকের বাইরেও সত্য । সাধারণত, পরিবর্তে:

    int result;
    (...)
    result = f1();
    if (result) then { (...) }
    (...)
    result = f2();
    if (result) then { (...) }

এটি লিখতে নিরাপদ:

    (...)
    {
        int const result = f1();
        if (result) then { (...) }
    }
    (...)
    {
        int const result = f2();
        if (result) then { (...) }
    }

পার্থক্যটি সামান্য মনে হতে পারে, বিশেষত এরকম একটি ছোট উদাহরণের ক্ষেত্রে। কিন্তু একটি বৃহত্তর কোড বেস উপর, এটা সাহায্য করবে: এখন কিছু পরিবহন কোন ঝুঁকি resultথেকে মান f1()থেকে f2()ব্লক। প্রত্যেকে resultকঠোরভাবে তার নিজস্ব ক্ষেত্রের মধ্যে সীমাবদ্ধ, এর ভূমিকাটিকে আরও নির্ভুল করে তোলে। একটি পর্যালোচক দৃষ্টিকোণ থেকে, এটি অনেক সুন্দর, যেহেতু চিন্তাভাবনা এবং ট্র্যাক করার জন্য তার কাছে দীর্ঘ পরিসীমা রাষ্ট্রীয় ভেরিয়েবল রয়েছে

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

পরিপূরক তথ্য

ওপেন-সোর্স সরঞ্জাম CppCheck (সি / সি ++ কোডের জন্য একটি স্ট্যাটিক বিশ্লেষণ সরঞ্জাম) ভেরিয়েবলের অনুকূল সুযোগ সম্পর্কে কিছু দুর্দান্ত ইঙ্গিত সরবরাহ করে।

বরাদ্দের বিষয়ে মন্তব্যের জবাবে: উপরের নিয়মটি সিটিতে সত্য, তবে কিছু সি ++ শ্রেণির জন্য নাও হতে পারে।

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

তবে সি ++ ক্লাসের জন্য এই কনস্ট্রাক্টর জিনিসটি রয়েছে যা সম্পর্কে আমি খুব কম জানি। আমার ধারণা, বরাদ্দ সম্ভবত সমস্যা হতে পারে না, যেহেতু সংকলক একই স্থানটি পুনরায় ব্যবহার করার জন্য যথেষ্ট চালাক হবে, তবে প্রতিটি লুপের পুনরাবৃত্তিতে প্রাথমিককরণের সম্ভাবনা রয়েছে।


4
দুর্দান্ত উত্তর। এটি হ'ল আমি যা খুঁজছিলাম, এমনকি এমন কিছু যা কিছু আমি বুঝতে পারি নি সে সম্পর্কে কিছুটা অন্তর্দৃষ্টি দিয়েছিলাম। আমি বুঝতে পারি নি যে সুযোগটি কেবল লুপের মধ্যেই রয়েছে। প্রতিক্রিয়ার জন্য আপনাকে ধন্যবাদ!
জেরামিরআর

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

4
@ জেরামিআরআর: একেবারে না - কম্পাইলারের কাছে জানার কোনও উপায় নেই যে বস্তুটির নির্মাণকারী বা ডেস্ট্রাক্টরটিতে অর্থপূর্ণ পার্শ্ব-প্রতিক্রিয়া রয়েছে।
iljarn 21

2
@ আয়রন: অন্যদিকে, আপনি যখন প্রথমে আইটেমটি ঘোষণা করেন, আপনি কেবলমাত্র অ্যাসাইনমেন্ট অপারেটরের কাছে অনেকগুলি কল পান; যা সাধারণত কোনও অবজেক্ট তৈরি এবং ধ্বংস করার মতো ব্যয় করে।
বিলি ওনিল

4
@ বিলিওনজিয়েল: stringএবং vectorবিশেষত অ্যাসাইনমেন্ট অপারেটর প্রতিটি লুপ বরাদ্দ করা বাফার পুনরায় ব্যবহার করতে পারে, যা (আপনার লুপের উপর নির্ভর করে) একটি বিশাল সময় সাশ্রয় হতে পারে।
হাঁস Mooing

22

সাধারণত এটি খুব কাছাকাছি রাখা খুব ভাল অনুশীলন।

কিছু ক্ষেত্রে, পারফরম্যান্সের মতো এমন বিবেচনা হবে যা ভেরিয়েবলটিকে লুপের বাইরে টেনে তোলার ন্যায্যতা দেয়।

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

মনে করুন আপনি এই অপ্রয়োজনীয় সৃষ্টি / বরাদ্দগুলি এড়াতে চেয়েছিলেন, আপনি এটিকে লিখে রাখবেন:

for (int counter = 0; counter <= 10; counter++) {
   // compiler can pull this out
   const char testing[] = "testing";
   cout << testing;
}

অথবা আপনি ধ্রুবকটি টানতে পারেন:

const std::string testing = "testing";
for (int counter = 0; counter <= 10; counter++) {
   cout << testing;
}

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

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

for (int counter = 0; counter <= 10; counter++) {
   string testing = "testing";
   cout << testing;
}

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

এটা করছি:

string testing;
for (int counter = 0; counter <= 10; counter++) {
   testing = "testing";
   cout << testing;
}

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

সুতরাং আপনি এই সমস্ত বিকল্পগুলির (এবং আরও) কী করবেন? এটি একটি ডিফল্ট হিসাবে খুব কাছাকাছি রাখুন - যতক্ষণ না আপনি ব্যয়গুলি ভালভাবে বুঝতে এবং আপনার কখন কী বিচ্যুত হওয়া উচিত তা না জানা পর্যন্ত।


1
ফ্লোট বা ইন্টির মতো বুনিয়াদি ডেটাটাইপগুলি সম্পর্কে, লুপের অভ্যন্তরে ভেরিয়েবল ঘোষণার ফলে লুপের বাইরে যে ভেরিয়েবলটি ঘোষণার চেয়ে ধীর হয়ে যায় কারণ প্রতিটি প্রতিটি পুনরাবৃত্তির জন্য একটি স্থান বরাদ্দ করতে হবে?
কাস্পারভ ৯২

2
@ কাস্পারভ ৯২ এর সংক্ষিপ্ত উত্তরটি হ'ল না that উন্নত পাঠযোগ্যতা / স্থানীয়তার জন্য যখন সম্ভব হয় তখন এই অপটিমাইজেশনটিকে উপেক্ষা করুন এবং এটিকে লুপে রাখুন The আরও বিশদে, এটি শেষ পর্যন্ত সংকলকটির সিদ্ধান্ত নেওয়ার জন্য, প্ল্যাটফর্মের জন্য সর্বোত্তম কী, সর্বোত্তমকরণ ইত্যাদির উপর ভিত্তি করে a একটি লুপের অভ্যন্তরে একটি সাধারণ অন্তর্নিহিত / ভাসমান সাধারণত স্ট্যাকের উপরে রাখা হবে। একটি সংকলক অবশ্যই লুপের বাইরে চলে যেতে পারে এবং যদি এটি করার ক্ষেত্রে কোনও অপ্টিমাইজেশন থাকে তবে সঞ্চয়স্থানটিকে পুনরায় ব্যবহার করতে পারে। ব্যবহারিক উদ্দেশ্যে, এটি একটি খুব খুব ছোট অপ্টিমাইজেশন হবে ...
জাস্টিন

1
@ কাস্পারভ ৯২… (চালিয়ে যাওয়া) যা আপনি কেবল পরিবেশ / অ্যাপ্লিকেশনগুলিতে বিবেচনা করবেন যেখানে প্রতিটি চক্র গণনা করা হবে। এই ক্ষেত্রে, আপনি কেবল সমাবেশ ব্যবহার বিবেচনা করতে চাইতে পারেন।
জাস্টিন

14

সি ++ এর জন্য এটি আপনি কী করছেন তার উপর নির্ভর করে। ঠিক আছে, এটি বোকা কোড তবে কল্পনা করুন

class myTimeEatingClass
{
 public:
 //constructor
      myTimeEatingClass()
      {
          sleep(2000);
          ms_usedTime+=2;
      }
      ~myTimeEatingClass()
      {
          sleep(3000);
          ms_usedTime+=3;
      }
      const unsigned int getTime() const
      {
          return  ms_usedTime;
      }
      static unsigned int ms_usedTime;
};
myTimeEatingClass::ms_CreationTime=0; 
myFunc()
{
    for (int counter = 0; counter <= 10; counter++) {

        myTimeEatingClass timeEater();
        //do something
    }
    cout << "Creating class took "<< timeEater.getTime() <<"seconds at all<<endl;

}
myOtherFunc()
{
    myTimeEatingClass timeEater();
    for (int counter = 0; counter <= 10; counter++) {
        //do something
    }
    cout << "Creating class took "<< timeEater.getTime() <<"seconds at all<<endl;

}

আপনি MyFunc এর আউটপুট না পাওয়া পর্যন্ত 55 সেকেন্ড অপেক্ষা করবেন। প্রতিটি লুপ কনট্রাক্টর এবং ডেস্ট্রাক্টর একসাথে শেষ করতে 5 সেকেন্ডের প্রয়োজন।

আপনি myOtherFunc এর আউটপুট না পাওয়া পর্যন্ত আপনার 5 সেকেন্ডের প্রয়োজন হবে।

অবশ্যই এটি একটি উন্মাদ উদাহরণ is

তবে এটি চিত্রিত করে যে যখন প্রতিটি লুপ একই নির্মাণ শেষ করতে পারে যখন কনস্ট্রাক্টর এবং / অথবা ডেস্ট্রাক্টরকে কিছু সময় প্রয়োজন হয়।


2
ঠিক আছে, প্রযুক্তিগতভাবে দ্বিতীয় সংস্করণে আপনি কেবলমাত্র 2 সেকেন্ডের মধ্যে আউটপুট পাবেন, কারণ আপনি এখনও অবজেক্টটি ধ্বংস করেন নি .....
ক্রাইস

12

আমি জেরেমিআর এর প্রশ্নের উত্তর দেওয়ার জন্য পোস্ট করি নি (যেমন তারা ইতিমধ্যে উত্তর দিয়ে গেছে); পরিবর্তে, আমি কেবল পরামর্শ দেওয়ার জন্য পোস্ট করেছি।

জেরেমিআর-এর কাছে, আপনি এটি করতে পারেন:

{
  string someString = "testing";   

  for(int counter = 0; counter <= 10; counter++)
  {
    cout << someString;
  }

  // The variable is in scope.
}

// The variable is no longer in scope.

আপনি বুঝতে পেরেছেন কিনা আমি জানি না (আমি প্রথম প্রোগ্রামিং শুরু করার সময় আমি করিনি), বন্ধনীগুলি (যতক্ষণ না তারা জোড়ায় থাকে) কোডের মধ্যে যে কোনও জায়গায় স্থাপন করা যেতে পারে, "যদি", "জন্য" পরে নয়, যখন ", ইত্যাদি"

আমার কোডটি মাইক্রোসফ্ট ভিজ্যুয়াল সি ++ 2010 এক্সপ্রেসে সংকলিত হয়েছে, তাই আমি জানি এটি কার্যকর হয়; এছাড়াও, আমি বন্ধনীগুলির মধ্যে এটির সংজ্ঞায়িত করার বাইরে ভেরিয়েবলটি ব্যবহার করার চেষ্টা করেছি এবং আমি একটি ত্রুটি পেয়েছি, তাই আমি জানি যে ভেরিয়েবলটি "নষ্ট" হয়েছিল।

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


4
আমার কাছে এটি একটি খুব বৈধ উত্তর যা প্রশ্নের সাথে সরাসরি যুক্ত একটি পরামর্শ এনে দেয়। আপনি আমার ভোট আছে!
অ্যালেক্সিস লেকার্ক

0

এটি একটি খুব ভাল অনুশীলন, যেহেতু উপরের সমস্ত উত্তরই প্রশ্নের খুব ভাল তাত্ত্বিক দিক সরবরাহ করে আমাকে কোডের একটি ঝলক দেই, আমি জিইইকেএসফোরজিইকেএস-এর উপর ডিএফএস সমাধান করার চেষ্টা করছিলাম, আমি অপ্টিমাইজেশনের সমস্যার মুখোমুখি হচ্ছি ...... যদি আপনি চেষ্টা করেন তবে লুপের বাইরে পূর্ণসংখ্যা ঘোষণার কোডটি সমাধান করুন আপনাকে অপ্টিমাইজেশন ত্রুটি দেবে ..

stack<int> st;
st.push(s);
cout<<s<<" ";
vis[s]=1;
int flag=0;
int top=0;
while(!st.empty()){
    top = st.top();
    for(int i=0;i<g[top].size();i++){
        if(vis[g[top][i]] != 1){
            st.push(g[top][i]);
            cout<<g[top][i]<<" ";
            vis[g[top][i]]=1;
            flag=1;
            break;
        }
    }
    if(!flag){
        st.pop();
    }
}

এখন লুপের ভিতরে পূর্ণসংখ্যা রাখুন এটি আপনাকে সঠিক উত্তর দেবে ...

stack<int> st;
st.push(s);
cout<<s<<" ";
vis[s]=1;
// int flag=0;
// int top=0;
while(!st.empty()){
    int top = st.top();
    int flag = 0;
    for(int i=0;i<g[top].size();i++){
        if(vis[g[top][i]] != 1){
            st.push(g[top][i]);
            cout<<g[top][i]<<" ";
            vis[g[top][i]]=1;
            flag=1;
            break;
        }
    }
    if(!flag){
        st.pop();
    }
}

এটি স্যার ২ য় মন্তব্যে কী বলছেন তা পুরোপুরি প্রতিফলিত করে .... এখানে চেষ্টা করুন https: //pੈਕਟ.geeksforgeeks.org/problems/depth-first-traversal-for-a- অনুচ্ছেদ / 1 । শুধু একটি শট দিন .... আপনি এটি পাবেন। এই সাহায্য আশা করি।


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

আপনার পোস্ট করা কোডটিতে সমস্যাটি সংজ্ঞা নয় বরং সূচনা অংশ is flagপ্রতিটি whileপুনরাবৃত্তিতে 0 এ পুনরায় পুনঃনির্মাণ করা উচিত । এটি একটি যুক্তির সমস্যা, সংজ্ঞা সমস্যা নয়।
মার্টিন ভের্নানউ

0

কে ও আর এর সি প্রোগ্রামিং ল্যাঙ্গুয়েজে অধ্যায় 4.8 ব্লক কাঠামো 2.এড। :

যখন কোনও ব্লক প্রবেশ করানো হয় তখন একটি ব্লকে একটি স্বয়ংক্রিয় পরিবর্তনশীল ঘোষিত এবং প্রারম্ভিক হয় initial

বইটিতে প্রাসঙ্গিক বিবরণটি দেখে আমি হয়তো মিস করেছি:

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

তবে একটি সহজ পরীক্ষা অনুষ্ঠিত অনুমানটি প্রমাণ করতে পারে:

 #include <stdio.h>                                                                                                    

 int main(int argc, char *argv[]) {                                                                                    
     for (int i = 0; i < 2; i++) {                                                                                     
         for (int j = 0; j < 2; j++) {                                                                                 
             int k;                                                                                                    
             printf("%p\n", &k);                                                                                       
         }                                                                                                             
     }                                                                                                                 
     return 0;                                                                                                         
 }                                                                                                                     
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.