প্রসঙ্গ
আমরা সি কোড পোর্টিং করছি যা মূলত পিআইসি মাইক্রোকন্ট্রোলারের জন্য একটি 8-বিট সি সংকলক ব্যবহার করে সংকলিত হয়েছিল। স্বাক্ষরযুক্ত গ্লোবাল ভেরিয়েবলগুলি (উদাহরণস্বরূপ, ত্রুটি কাউন্টার) শূন্যে ফিরে যাওয়া থেকে রোধ করার জন্য একটি সাধারণ আইডিয়োমটি হ'ল:
if(~counter) counter++;
বিটওয়াইড অপারেটরটি এখানে সমস্ত বিটকে উল্টে দেয় এবং counter
সর্বাধিক মানের চেয়ে কম হলে বিবৃতিটি সত্য হয়। গুরুত্বপূর্ণভাবে, ভেরিয়েবলের আকার নির্বিশেষে এটি কাজ করে।
সমস্যা
আমরা এখন জিসিসি ব্যবহার করে একটি 32-বিট এআরএম প্রসেসরটিকে লক্ষ্য করছি। আমরা লক্ষ্য করেছি যে একই কোডটি বিভিন্ন ফলাফল তৈরি করে। যতদূর আমরা বলতে পারি, দেখে মনে হচ্ছে বিটওয়াইস পরিপূরক অপারেশনটি এমন কোনও মান প্রত্যাবর্তন করে যা আমরা প্রত্যাশার চেয়ে আলাদা আকারের। এটি পুনরুত্পাদন করতে আমরা জিসিসিতে সংকলন করি:
uint8_t i = 0;
int sz;
sz = sizeof(i);
printf("Size of variable: %d\n", sz); // Size of variable: 1
sz = sizeof(~i);
printf("Size of result: %d\n", sz); // Size of result: 4
আউটপুট প্রথম লাইনে, আমরা যা প্রত্যাশা করব তা পাই: i
1 বাইট। তবে, বিটওয়াইসের পরিপূরকটি i
আসলে চারটি বাইট যা সমস্যার কারণ কারণ এটির সাথে এখন তুলনা করা প্রত্যাশিত ফলাফল দেয় না। উদাহরণস্বরূপ, যদি করা হয় (যেখানে i
সঠিকভাবে-সূচনা করা হয়েছে uint8_t
):
if(~i) i++;
আমরা i
0xFF থেকে 0x00 এ ফিরে "প্রায় মোড়ানো" দেখতে পাব । পূর্ববর্তী সংকলক এবং 8-বিট পিআইসির মাইক্রোকন্ট্রোলারের মধ্যে যেমনটি কাজ করা হয়েছিল তখন তার সাথে তুলনা করে এই আচরণটি জিসিসিতে আলাদা।
আমরা সচেতন যে আমরা এর মতো কাস্টিংয়ের মাধ্যমে সমাধান করতে পারি:
if((uint8_t)~i) i++;
অথবা দ্বারা
if(i < 0xFF) i++;
তবে এই উভয় কাজের ক্ষেত্রে ভেরিয়েবলের আকার অবশ্যই জানা উচিত এবং এটি সফ্টওয়্যার বিকাশকারীদের জন্য ত্রুটি-প্রবণ। কোডবেস জুড়ে এই ধরণের ওপরের সীমার চেকগুলি ঘটে। একাধিক আকারের ভেরিয়েবল রয়েছে (উদা।, uint16_t
এবং unsigned char
ইত্যাদি) এবং এগুলি অন্যথায় কাজ করা কোডবেসে পরিবর্তন করা এমন কিছু নয় যা আমরা প্রত্যাশিত।
প্রশ্ন
সমস্যাটি সম্পর্কে আমাদের উপলব্ধি কি সঠিক, এবং এর সমাধানের জন্য কি এমন বিকল্প রয়েছে যেগুলি আমরা এই প্রতিমাটি ব্যবহার করেছি সেখানে প্রতিটি ক্ষেত্রে পুনরায় দেখার প্রয়োজন হয় না? আমাদের ধারণাটি কি সঠিক, বিটওয়াইজ পরিপূরকের মতো কোনও ক্রিয়াকলাপটি অপারেন্ডের মতো একই আকারের ফলস্বরূপ ফিরে আসে? প্রসেসরের আর্কিটেকচারের উপর নির্ভর করে এটি মনে হচ্ছে এটি ভেঙে যাবে। আমার মনে হচ্ছে আমি পাগল বড়ি নিচ্ছি এবং সি এর চেয়ে কিছুটা বেশি বহনযোগ্য হওয়া উচিত। আবার, এটি সম্পর্কে আমাদের বোঝার ভুল হতে পারে।
উপরিভাগে এটি কোনও বিশাল সমস্যার মতো মনে হচ্ছে না তবে এই পূর্বে কাজ করা প্রতিমাটি কয়েকশ জায়গায় ব্যবহার করা হয়েছে এবং ব্যয়বহুল পরিবর্তনগুলি নিয়ে এগিয়ে যাওয়ার আগে আমরা এটি বুঝতে আগ্রহী।
দ্রষ্টব্য: এখানে আপাতদৃষ্টিতে অনুরূপ তবে সঠিক ডুপ্লিকেট প্রশ্ন নেই: চরে বিটওয়াস অপারেশন 32 বিট ফলাফল দেয়
আমি সেখানে আলোচিত ইস্যুর আসল চরিত্রটি দেখতে পাইনি, অর্থাত্ অপারেটরটিতে যা হয়েছে তার চেয়ে বিটওয়াইসের পরিপূরকের ফলাফলের আকারটি আলাদা being