সিতে কেন অস্থিরতার প্রয়োজন?


উত্তর:


423

উদ্বোধকটি কম্পাইলারকে বলে যে কোনও কিছুকেই উদ্বায়ী ভেরিয়েবলের সাথে অনুকূল করতে হবে না।

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

ধরা যাক আপনার কাছে একটি সামান্য টুকরো হার্ডওয়্যার রয়েছে যা কোথাও র‌্যামে ম্যাপ করা হয়েছে এবং এর দুটি ঠিকানা রয়েছে: একটি কমান্ড পোর্ট এবং একটি ডেটা পোর্ট:

typedef struct
{
  int command;
  int data;
  int isbusy;
} MyHardwareGadget;

এখন আপনি কিছু আদেশ পাঠাতে চান:

void SendCommand (MyHardwareGadget * gadget, int command, int data)
{
  // wait while the gadget is busy:
  while (gadget->isbusy)
  {
    // do nothing here.
  }
  // set data first:
  gadget->data    = data;
  // writing the command starts the action:
  gadget->command = command;
}

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

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

এটি সঠিক সংস্করণ:

   void SendCommand (volatile MyHardwareGadget * gadget, int command, int data)
    {
      // wait while the gadget is busy:
      while (gadget->isbusy)
      {
        // do nothing here.
      }
      // set data first:
      gadget->data    = data;
      // writing the command starts the action:
      gadget->command = command;
    }

46
ব্যক্তিগতভাবে, আমি হার্ডওয়ারের সাথে কথা বলার সময় পূর্ণসংখ্যার আকারটি স্পষ্টতা হিসাবে পছন্দ করতাম যেমন int8 / int16 / int32। যদিও দুর্দান্ত উত্তর;)
টনিলো

22
হ্যাঁ, আপনার একটি নির্দিষ্ট নিবন্ধের আকারের সাথে জিনিসগুলি ঘোষণা করা উচিত তবে ওহে - এটি কেবল উদাহরণ।
নীল পিপেনব্রিংক

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

14
সি স্পেসিফিকেশন আরও শক্ত করে পড়ুন। অস্থির কেবল মেমরি-ম্যাপযুক্ত ডিভাইস I / O বা অ্যাসিঙ্ক্রোনাস বাধা ফাংশন দ্বারা স্পর্শ করা মেমরির উপর আচরণের সংজ্ঞা দেয়। এটি থ্রেডিং সম্পর্কে কিছুই বলে না , এবং এমন একটি সংকলক যা একাধিক থ্রেড দ্বারা স্পর্শ করা মেমরির অ্যাক্সেসকে দূরে সরিয়ে দেয় con
পূর্বসূরী

17
@ টলোমিয়া: সম্পূর্ণ ভুল দু: খিত 17 জন এটি জানেন না। উদ্বায়ী একটি মেমরি বেড়া নয়। এটি কেবলমাত্র দৃশ্যমান নয় এমন পার্শ্ব প্রতিক্রিয়া অনুমানের ভিত্তিতে অনুকূলকরণের সময় কোড এলিজেন্স এড়ানো সম্পর্কিত ।
v.oddou

187

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


অস্তিত্বের মধ্যে এসেছেন? ´volatile` মূলত সি ++ থেকে ধার ছিল না? ঠিক আছে, আমি মনে করি ...
সিনট্যাক্সারর


4
@ ফ্যাশব্রো: উদ্দেশ্যটি volatileছিল কম্পাইলারদের কোড অপ্টিমাইজ করা সম্ভব করা যখন এখনও প্রোগ্রামাররা এই শব্দার্থক শব্দগুলি অর্জন করতে পারে যা এই ধরনের অপ্টিমাইজেশন ছাড়াই অর্জন করতে পারে। স্ট্যান্ডার্ডের লেখকরা প্রত্যাশা করেছিলেন যে লক্ষ্য প্রয়োগকারীরা তাদের লক্ষ্য প্ল্যাটফর্ম এবং অ্যাপ্লিকেশন ক্ষেত্রগুলি বিবেচনা করে যা কিছু শব্দার্থক কাজে লাগবে তা সমর্থন করবে এবং আশা করেনি যে সংকলক লেখকরা সর্বনিম্ন মানের শব্দার্থকগুলি প্রস্তাব করবে যা স্ট্যান্ডার্ডের সাথে সঙ্গতিপূর্ণ এবং 100% নয় বোকা (নোট করুন যে স্ট্যান্ডার্ডের লেখকরা স্পষ্টভাবে
যুক্তিতে

1
... যে কোনও বাস্তবের পক্ষে যথাযথভাবে কোনও উদ্দেশ্যে উপযুক্ত হওয়ার জন্য পর্যাপ্ত মানের হওয়া ছাড়া এটি বাস্তবায়ন সম্ভব, তবে তারা তা প্রতিরোধ করার প্রয়োজন মনে করেননি)।
সুপারক্যাট

1
@ সাইন্ট্যাক্সেরর যখন সি ++ (প্রথম প্রকাশ এবং প্রথম মানের উভয় ক্ষেত্রে) এর চেয়ে এক দশকেরও বেশি বয়সী ছিল তখন এটি সি ++ থেকে কীভাবে ধার করা যাবে?
ফুক্লভ

178

এর জন্য আরেকটি ব্যবহার volatileহ'ল সিগন্যাল হ্যান্ডলার। আপনার যদি এই জাতীয় কোড থাকে:

int quit = 0;
while (!quit)
{
    /* very small loop which is completely visible to the compiler */
}

সংকলকটি লুপের বডিটি quitভেরিয়েবলটিকে স্পর্শ করে না এবং লুপটিকে একটি while (true)লুপে রূপান্তর করতে পারে তা লক্ষ্য করার অনুমতি দেওয়া হয় । এমনকি যদি quitভেরিয়েবলটি সিগন্যাল হ্যান্ডলারের জন্য SIGINTএবং এর জন্য সেট করা থাকে SIGTERM; সংকলকটি এটি জানার কোনও উপায় নেই।

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


আপনি যখন বলেন "সংকলকটি প্রতিবার এটি লোড করতে বাধ্য হয়, কম্পাইলার যখন কোনও নির্দিষ্ট ভেরিয়েবলকে অনুকূলিত করার সিদ্ধান্ত নেয় এবং আমরা চলকটিকে অস্থির হিসাবে ঘোষণা করি না, রান টাইমে নির্দিষ্ট ভেরিয়েবল মেমরিতে নয় সিপিইউ রেজিস্টারে লোড হয় is ?
অমিত সিং তোমার

1
@ অমিতসিংহটুমার এর অর্থ যা বোঝায়: প্রত্যেকবার কোডটি মূল্য পরীক্ষা করে, এটি পুনরায় লোড করা হয়। অন্যথায়, সংকলকটিকে ধরে নিতে দেওয়া হয় যে ভেরিয়েবলের কোনও রেফারেন্স নেয় না এমন ফাংশনগুলি এটি সংশোধন করতে পারে না, সুতরাং উপরের লুপটি সেট না করে বলে সিজারবিকে উদ্দেশ্য করে ধরে নেওয়া, সংকলক ধরে নিলে quitএটি একটি ধ্রুবক লুপে অনুকূলিত করতে পারে quitপুনরাবৃত্তির মধ্যে পরিবর্তন করার কোনও উপায় নেই । এনবি: প্রকৃত থ্রেডস্যাফ প্রোগ্রামিংয়ের জন্য এটি অবশ্যই ভাল বিকল্প নয়।
আন্ডারস্কোর_ডি

প্রস্থান যদি একটি বিশ্বব্যাপী পরিবর্তনশীল হয়, তবে সংকলকটি যখন লুপটি সঠিক করবে না, সঠিক?
পিয়েরে জি।

2
@PierreG। না, সংকলক সর্বদা ধরে নিতে পারে যে কোডটি একক থ্রেডযুক্ত, অন্যথায় না বলা পর্যন্ত। অর্থাৎ, volatileবা অন্যান্য চিহ্নিতকারীদের অনুপস্থিতিতে , এটি ধরে নেওয়া হবে যে লুপের বাইরে কোনও কিছুই সেই পরিবর্তনশীলটিকে পরিবর্তন করে না যখন একবার লুপটিতে প্রবেশ করে, এমনকি এটি বৈশ্বিক পরিবর্তনশীল।
সিজারব

1
@PierreG। হ্যাঁ, সংকলন উদাহরণস্বরূপ চেষ্টা extern int global; void fn(void) { while (global != 0) { } }সঙ্গে gcc -O3 -Sএবং তার ফলে সমাবেশ ফাইল তাকান, আমার মেশিনে এটা আছে movl global(%rip), %eax; testl %eax, %eax; je .L1; .L4: jmp .L4, অর্থাৎ, বিশ্বব্যাপী শূন্য না হলে একটি অসীম লুপ। তারপরে যুক্ত করার চেষ্টা করুন volatileএবং পার্থক্যটি দেখুন।
সিজারব

60

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


30

আন্দ্রেই আলেকজান্দ্রেস্কুর এই নিবন্ধটি দেখুন, " অস্থির - মাল্টিথ্রেডেড প্রোগ্রামার সেরা বন্ধু "

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

নিবন্ধটি উভয় ক্ষেত্রে প্রযোজ্য Cএবং C++

স্কট মায়ারস এবং আন্দ্রে আলেকজান্দ্রেস্কুর " সি ++ এবং ডাবল-চেকড লকিংয়ের বিপদগুলি " নিবন্ধটি দেখুন :

তাই কিছু মেমোরি অবস্থানের সাথে কাজ করার সময় (যেমন মেমরি ম্যাপযুক্ত পোর্ট বা আইএসআর দ্বারা ব্যবহৃত মেমরি [[বিঘ্নিত পরিষেবার রুটিন]]) কিছু অপ্টিমাইজেশন স্থগিত করতে হবে। এই জায়গাগুলির জন্য বিশেষ চিকিত্সা নির্দিষ্ট করার জন্য অস্থির উপস্থিতি রয়েছে, বিশেষত: (1) একটি উদ্বায়ী ভেরিয়েবলের বিষয়বস্তু "অস্থির" (সংকলকের অজানা মাধ্যমে পরিবর্তিত হতে পারে), (২) অস্থির ডেটাগুলিতে সমস্ত লিখেছে "পর্যবেক্ষণযোগ্য" তাই তারা অবশ্যই ধর্মীয়ভাবে মৃত্যুদন্ড কার্যকর করা উচিত এবং (3) অস্থির ডেটাতে সমস্ত ক্রিয়াকলাপ ক্রম অনুসারে কার্যকর করা হয় যেখানে তারা উত্স কোডে প্রদর্শিত হয়। প্রথম দুটি নিয়ম যথাযথ পড়া এবং লেখা নিশ্চিত করে। সর্বশেষ একটি ইনপুট এবং আউটপুটকে মেশানো I / O প্রোটোকলগুলির প্রয়োগের অনুমতি দেয়। এটি অনানুষ্ঠানিকভাবে সি এবং সি ++ এর অস্থির গ্যারান্টিযুক্ত।


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

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

পরবর্তী নিবন্ধটি প্রকৃতপক্ষে স্পষ্টভাবে জানিয়েছে যে পাঠগুলি পার্শ্ব প্রতিক্রিয়া। প্রাক্তনটি ইঙ্গিত দেয় যে পাঠগুলি যথাযথভাবে সম্পাদন করা যায় না, তবে তাদের পুরোপুরিভাবে বঞ্চিত হওয়ার সম্ভাবনাটি কমে যায় বলে মনে হয় না।
সুপারক্যাট

"কম্পাইলার একটি রেজিস্টার এটা ক্যাশে করার অনুমতি না" - সর্বাধিক আরআইএসসি arcitectures AE রেজিস্টার করো-মেশিন, তাই কোনো পাঠযোগ্য সংশোধন-রাইট হয়েছে একটি রেজিস্টার বস্তুর ক্যাশে করা হয়। volatileপারমাণবিকতা গ্যারান্টি দেয় না।
এই সাইটের পক্ষে খুব সৎ

1
@ ওলাফ: একটি রেজিস্টারটিতে কিছু লোড করা ক্যাশে করার মতো জিনিস নয়। ক্যাশিং লোড বা স্টোর বা তাদের সময় সংখ্যার উপর প্রভাব ফেলবে।
সুপারক্যাট

28

আমার সহজ ব্যাখ্যাটি হ'ল:

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

উদাহরণ স্বরূপ:

bool usb_interface_flag = 0;
while(usb_interface_flag == 0)
{
    // execute logic for the scenario where the USB isn't connected 
}

উপরের কোড থেকে, সংকলকটি usb_interface_flag0 হিসাবে সংজ্ঞায়িত হিসাবে মনে হতে পারে , এবং সেই সময় লুপটি চিরতরে শূন্য হবে। অপ্টিমাইজেশনের পরে, সংকলকটি এটি while(true)সর্বকালের হিসাবে বিবেচনা করবে , যার ফলে অসীম লুপ হবে।

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


19

অস্থির জন্য একটি প্রান্তিক ব্যবহার নিম্নলিখিত। বলুন আপনি কোনও ফাংশনের সংখ্যাগত ডেরিভেটিভ গণনা করতে চান f:

double der_f(double x)
{
    static const double h = 1e-3;
    return (f(x + h) - f(x)) / h;
}

সমস্যাটি হ'ল রাউন্ডঅফ ত্রুটির কারণে x+h-xসাধারণত সমান হয় না h। এটি সম্পর্কে চিন্তা করুন: আপনি যখন খুব কাছের সংখ্যার বিয়োগ করেন, আপনি প্রচুর উল্লেখযোগ্য সংখ্যা হারাবেন যা ডেরাইভেটিভের গণনাকে নষ্ট করতে পারে (চিন্তা করুন 1.00001 - 1)। একটি সম্ভাব্য কাজ হতে পারে

double der_f2(double x)
{
    static const double h = 1e-3;
    double hh = x + h - x;
    return (f(x + hh) - f(x)) / hh;
}

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

    volatile double hh = x + h;
    hh -= x;

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


ব্যবহার hবা hhডেরিভেটিভ সূত্র মধ্যে পার্থক্য কি ? কখন hhগণনা করা হয় শেষ সূত্রটি এটিকে প্রথমটির মতো ব্যবহার করে, কোনও পার্থক্য ছাড়াই। এটা হতে হবে (f(x+h) - f(x))/hh?
সের্গেই hu

2
মধ্যে পার্থক্য hএবং hhযে hhঅপারেশন দুটি কিছু নেতিবাচক ক্ষমতায় ছেঁটে ফেলা হয়েছে x + h - x। এই ক্ষেত্রে, x + hhএবং xঠিক দ্বারা পৃথক hh। আপনি আপনার সূত্রটিও নিতে পারেন, এটি একই ফলাফল দেবে, যেহেতু x + hএবং x + hhসমান (এটি হ'ল যা এখানে গুরুত্বপূর্ণ।
আলেকজান্দ্রি সি

3
এটি লেখার আরও পঠনযোগ্য উপায় কি নয় x1=x+h; d = (f(x1)-f(x))/(x1-x)? অস্থির ব্যবহার না করে।
সের্গেই hu

কোনও রেফারেন্স যে একটি সংকলক ফাংশনটির দ্বিতীয় লাইনটি মুছতে পারে?
কফি টেবিলস্প্রেসো

@ কফি টেবিলস্প্রেসো: না, দুঃখিত। ভাসমান পয়েন্ট সম্পর্কে আমি যত বেশি জানি, ততই আমি বিশ্বাস করি যে সংকলকটি কেবল এটির সাথে -ffast-mathবা সমতুল্যভাবে স্পষ্টভাবে যদি বলা হয় তবে এটি অপ্টিমাইজ করার অনুমতি রয়েছে ।
আলেকজান্দ্রি সি

11

দুটি ব্যবহার আছে। এম্বেডড ডেভলপমেন্টে এগুলি বিশেষত বেশি ব্যবহৃত হয়।

  1. সংকলকটি অস্থায়ী কীওয়ার্ডের সাথে সংজ্ঞায়িত ভেরিয়েবলগুলি ব্যবহার করে এমন ফাংশনগুলি অনুকূল করবে না

  2. অস্থিরতা র‌্যাম, রম ইত্যাদিতে সঠিক মেমোরি অবস্থানগুলিতে অ্যাক্সেস করতে ব্যবহৃত হয় ... মেমরি-ম্যাপযুক্ত ডিভাইসগুলি নিয়ন্ত্রণ করতে, সিপিইউ রেজিস্টারগুলিতে অ্যাক্সেস করতে এবং নির্দিষ্ট মেমরির অবস্থানগুলি সনাক্ত করতে এটি প্রায়শই ব্যবহৃত হয়।

সমাবেশ তালিকা সহ উদাহরণগুলি দেখুন। পুনরায়: এম্বেডড ডেভলপমেন্টে সি "অস্থির" কীওয়ার্ডের ব্যবহার


"সংকলকটি অস্থায়ী কীওয়ার্ড দ্বারা সংজ্ঞায়িত ভেরিয়েবলগুলি ব্যবহার করে এমন ফাংশনগুলি অনুকূল করে না" - এটি সাধারণ ভুল plain
এই সাইটের পক্ষে খুব সৎ

10

অস্থিরতাও দরকারী, যখন আপনি কম্পাইলারকে একটি নির্দিষ্ট কোড সিকোয়েন্সটি অনুকূলকরণ করতে বাধ্য করবেন না (যেমন মাইক্রো-বেঞ্চমার্ক লেখার জন্য)।


10

আমি অন্য একটি দৃশ্যের উল্লেখ করব যেখানে অস্থিরতা গুরুত্বপূর্ণ।

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

যদি আপনি অ-উদ্বায়ী বস্তুগুলিতে (উত্স কোড স্তরে) পয়েন্টারগুলির মাধ্যমে মেমরি-ম্যাপযুক্ত ফাইলের ডেটা অ্যাক্সেস করেন তবে সংকলকটির দ্বারা উত্পন্ন কোডটি আপনাকে সচেতন না করে একই তথ্য একাধিকবার আনতে পারে।

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

আপনি যদি সুরক্ষা সম্পর্কে চিন্তা করেন এবং আপনার উচিত, এটি বিবেচনা করার জন্য একটি গুরুত্বপূর্ণ দৃশ্য।


7

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


"র্যামের প্রকৃত ঠিকানা" বা "ক্যাশে বাইপাস" বলতে কোনও সংকলক অস্থির হয় না।
কৌতূহলী

6

উইকি সম্পর্কে সবকিছু বলে volatile:

এবং লিনাক্স কার্নেলের ডকটি সম্পর্কে একটি দুর্দান্ত স্বরলিপি দেয় volatile:


5

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

আমি বলব, তার উদাহরণটি উপযুক্ত নয় volatilevolatileকেবলমাত্র এটির জন্য ব্যবহৃত হয়: সংকলকটিকে দরকারী এবং পছন্দসই অপ্টিমাইজেশন করা থেকে বিরত রাখুন । এটি থ্রেড নিরাপদ, পারমাণবিক অ্যাক্সেস বা এমনকি মেমরির ক্রম সম্পর্কে কিছুই নয়।

সেই উদাহরণে:

    void SendCommand (volatile MyHardwareGadget * gadget, int command, int data)
    {
      // wait while the gadget is busy:
      while (gadget->isbusy)
      {
        // do nothing here.
      }
      // set data first:
      gadget->data    = data;
      // writing the command starts the action:
      gadget->command = command;
    }

কেবলমাত্র gadget->data = dataপূর্বে gadget->command = commandকেবল সংকলক দ্বারা সংকলিত কোডে গ্যারান্টিযুক্ত। চলমান সময়ে, প্রসেসর সম্ভবত প্রসেসরের আর্কিটেকচার সম্পর্কিত ডেটা এবং কমান্ড অ্যাসাইনমেন্টটি পুনরায় অর্ডার করে। হার্ডওয়্যারটি ভুল ডেটা পেতে পারে (ধরুন গ্যাজেটটি হার্ডওয়্যার আই / ও-তে ম্যাপ করা আছে)। ডেটা এবং কমান্ড কার্যভারের মধ্যে মেমরি বাধা প্রয়োজন


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

5

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

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

যেহেতু বিভিন্ন প্ল্যাটফর্মের বিভিন্ন উপায়ে কোনও সংকলকের নিয়ন্ত্রণের বাইরে অবজেক্টগুলি পর্যবেক্ষণ বা সংশোধন করা যেতে পারে, তাই উপযুক্ত যে এই প্ল্যাটফর্মগুলির জন্য মানের সংকলকগুলি volatileশব্দার্থবিজ্ঞানের সঠিক হ্যান্ডলিংয়ের ক্ষেত্রে পৃথক হওয়া উচিত । দুর্ভাগ্যক্রমে, স্ট্যান্ডার্ডটি পরামর্শ দিতে ব্যর্থ হয়েছে যে কোনও প্ল্যাটফর্মের নিম্ন-স্তরের প্রোগ্রামিংয়ের উদ্দেশ্যে তৈরি মানের সংকলকগুলি এমনভাবে পরিচালনা volatileকরতে হবে যা সেই প্ল্যাটফর্মে কোনও নির্দিষ্ট পঠন / লেখার ক্রিয়াকলাপের যে কোনও এবং সমস্ত প্রাসঙ্গিক প্রভাবকে স্বীকৃতি দেয় many সুতরাং যে উপায়ে ব্যাকগ্রাউন্ড I / O এর মতো জিনিসগুলি এমনভাবে প্রক্রিয়া করা শক্ত করে তোলে যা দক্ষ তবে কিন্তু সংকলক "অপ্টিমাইজেশন" দ্বারা ভাঙা যায় না।


5

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


1
এই উত্তরে নতুন কিছু আছে যা আগে বলা হয়নি?
slfan

3

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


0

যথাযথভাবে এখানে অনেকের দ্বারা প্রস্তাবিত হিসাবে, অস্থায়ী কীওয়ার্ডের জনপ্রিয় ব্যবহারটি হ'ল ভোল্টাইল ভেরিয়েবলের অপ্টিমাইজেশন এড়িয়ে যাওয়া।

সবচেয়ে ভাল সুবিধা যা মনে আসে এবং অস্থিরতা সম্পর্কে পড়ার পরে উল্লেখযোগ্য তা হ'ল - এর ক্ষেত্রে পরিবর্তনশীলটির পিছনে ঘোরানো রোধ করাlongjmp । একটি স্থানীয় নয়।

এটার মানে কি?

এর সহজ অর্থ হ'ল আপনি অনাবন্ধিক স্ট্যাক করার পরে শেষ মানটি বজায় থাকবে পূর্ববর্তী কিছু স্ট্যাক ফ্রেমে ফিরে আসার জন্য ; সাধারণত কিছু ভুল পরিস্থিতিতে।

যেহেতু এটি এই প্রশ্নের আওতার বাইরে থাকবে, আমি setjmp/longjmpএখানে বিশদ বিবরণে যাচ্ছি না , তবে এটি সম্পর্কে পড়া ভাল; এবং কীভাবে অস্থিরতা বৈশিষ্ট্যটি সর্বশেষ মান ধরে রাখতে ব্যবহার করা যেতে পারে।


-2

এটি চলকগুলির স্বয়ংক্রিয় পরিবর্তনের মানগুলিতে সংকলকটিকে অনুমতি দেয় না। একটি অস্থির পরিবর্তনশীল গতিশীল ব্যবহারের জন্য।

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