আপনি কীভাবে কিছুটা সেট, সাফ এবং টগল করবেন?
আপনি কীভাবে কিছুটা সেট, সাফ এবং টগল করবেন?
উত্তর:
|
কিছুটা সেট করতে বিটওয়াইস বা অপারেটর ( ) ব্যবহার করুন ।
number |= 1UL << n;
এটি এর n
বিট সেট করবে number
। n
শূন্য হওয়া উচিত, যদি আপনি 1
স্ট্রেন বিট সেট করতে চান এবং আরও কিছুক্ষণ n-1
, আপনি যদি n
থ্রি বিট সেট করতে চান ।
এর চেয়ে প্রশস্ত 1ULL
হলে ব্যবহার করুন ; এর প্রস্থের চেয়ে বেশি দ্বারা স্থানান্তরিত করা কোথায় অনির্ধারিত আচরণ হয় তা মূল্যায়ন করার পরেও এর প্রচার হয় না । একই উদাহরণ বাকী সমস্ত উদাহরণের ক্ষেত্রেও প্রযোজ্য।number
unsigned long
1UL << n
1UL << n
long
&
কিছুটা সাফ করতে বিটওয়াইস এবং অপারেটর ( ) ব্যবহার করুন ।
number &= ~(1UL << n);
এটি এর n
বিট সাফ করবে number
। আপনাকে অবশ্যই বিটওয়্যার নট অপারেটর ( ~
) এর সাথে বিট স্ট্রিংটি উল্টাতে হবে এবং তারপরে এটি।
এক্সওআর অপারেটর ( ^
) কিছুটা টগল করতে ব্যবহৃত হতে পারে।
number ^= 1UL << n;
যে টগল হবে n
এর ম বিট number
।
আপনি এটি চেয়েছিলেন না, তবে আমি এটি যুক্ত করতেও পারি।
কিছুটা পরীক্ষা করতে, n টি ডান দিকে সরিয়ে দিন, তারপরে খানিকটা এবং এটি:
bit = (number >> n) & 1U;
এটি ভেরিয়েবলের মধ্যে n
বি বিটের মান number
রাখবে bit
।
সেট n
থেকে তম বিট পারেন 1
বা 0
2 এর সম্পূরক সি ++ বাস্তবায়ন নিম্নলিখিত সঙ্গে অর্জন করা যেতে পারে:
number ^= (-x ^ number) & (1UL << n);
বিট n
যদি সেট করা হবে x
হয় 1
, এবং যদি সাফ x
হয় 0
। যদি x
অন্য কিছু মূল্য আছে, আপনি আবর্জনা পেতে। x = !!x
এটি 0 বা 1 এ উত্সাহিত করবে।
2 এর পরিপূরক অবহেলা আচরণকে স্বাধীন করার জন্য (যেখানে -1
1 এর পরিপূরক বা সাইন / মাত্রার সি ++ প্রয়োগের বিপরীতে সমস্ত বিট সেট করা আছে) স্বাক্ষরযুক্ত স্বাক্ষর ব্যবহার করুন।
number ^= (-(unsigned long)x ^ number) & (1UL << n);
অথবা
unsigned long newbit = !!x; // Also booleanize to force 0 or 1
number ^= (-newbit ^ number) & (1UL << n);
বহনযোগ্য বিট ম্যানিপুলেশনের জন্য স্বাক্ষরবিহীন প্রকারগুলি ব্যবহার করা সাধারণত একটি ভাল ধারণা।
অথবা
number = (number & ~(1UL << n)) | (x << n);
(number & ~(1UL << n))
সাফ করবে n
তম বিট এবং (x << n)
সেট হবে n
থেকে তম বিট x
।
সাধারণভাবে কোড অনুলিপি / পেস্ট না করাও একটি ভাল ধারণা এবং এত লোক প্রিপ্রোসেসর ম্যাক্রোগুলি ( সম্প্রদায়ের উইকির উত্তর আরও নীচে যেমন ) বা কোনও ধরণের এনক্যাপসুলেশন ব্যবহার করে।
bit = (number >> x) & 1
1
একটি int
আক্ষরিক, যা স্বাক্ষরিত হয়। সুতরাং এখানে সমস্ত ক্রিয়াকলাপ স্বাক্ষরযুক্ত সংখ্যার উপর পরিচালিত হয়, যা মানদণ্ড দ্বারা ভালভাবে সংজ্ঞায়িত হয় না। মান দুটি এর পরিপূরক বা পাটিগণিতের শিফট গ্যারান্টি দেয় না তাই এটি ব্যবহার করা ভাল 1U
।
number = number & ~(1 << n) | (x << n);
n-th বিটকে x এ পরিবর্তন করতে পছন্দ করি ।
Standard C ++ লাইব্রেরির ব্যবহার হচ্ছে: std::bitset<N>
।
অথবা বুস্ট সংস্করণ: boost::dynamic_bitset
।
আপনার নিজস্ব রোল করার দরকার নেই:
#include <bitset>
#include <iostream>
int main()
{
std::bitset<5> x;
x[1] = 1;
x[2] = 0;
// Note x[0-4] valid
std::cout << x << std::endl;
}
[Alpha:] > ./a.out
00010
বুস্ট সংস্করণ স্ট্যান্ডার্ড লাইব্রেরি সংকলন-সময়ের মাপের বিটসেটের সাথে তুলনা করে একটি রানটাইম আকারের বিটসেটের অনুমতি দেয় ।
অন্য বিকল্পটি হ'ল বিট ক্ষেত্রগুলি ব্যবহার করা:
struct bits {
unsigned int a:1;
unsigned int b:1;
unsigned int c:1;
};
struct bits mybits;
একটি 3-বিট ক্ষেত্র সংজ্ঞা দেয় (আসলে এটি তিনটি 1-বিট ফিল্ড)। বিট অপারেশনগুলি এখন কিছুটা (হাঃ) সহজ হয়ে গেছে:
কিছু সেট বা পরিষ্কার করতে:
mybits.b = 1;
mybits.c = 0;
কিছুটা টগল করতে:
mybits.a = !mybits.a;
mybits.b = ~mybits.b;
mybits.c ^= 1; /* all work */
কিছুটা পরীক্ষা করা হচ্ছে:
if (mybits.c) //if mybits.c is non zero the next line below will execute
এটি কেবল স্থির-আকারের বিট ক্ষেত্রগুলির সাথে কাজ করে। অন্যথায় আপনাকে পূর্ববর্তী পোস্টগুলিতে বর্ণিত বিট-টুইডলিং কৌশলগুলি অবলম্বন করতে হবে।
আমি বিট সেট এবং সাফ হ্যান্ডেল করতে একটি শিরোনাম ফাইলে সংজ্ঞায়িত ম্যাক্রোগুলি ব্যবহার করি:
/* a=target variable, b=bit number to act upon 0-n */
#define BIT_SET(a,b) ((a) |= (1ULL<<(b)))
#define BIT_CLEAR(a,b) ((a) &= ~(1ULL<<(b)))
#define BIT_FLIP(a,b) ((a) ^= (1ULL<<(b)))
#define BIT_CHECK(a,b) (!!((a) & (1ULL<<(b)))) // '!!' to make sure this returns 0 or 1
/* x=target variable, y=mask */
#define BITMASK_SET(x,y) ((x) |= (y))
#define BITMASK_CLEAR(x,y) ((x) &= (~(y)))
#define BITMASK_FLIP(x,y) ((x) ^= (y))
#define BITMASK_CHECK_ALL(x,y) (((x) & (y)) == (y)) // warning: evaluates y twice
#define BITMASK_CHECK_ANY(x,y) ((x) & (y))
BITMASK_CHECK(x,y) ((x) & (y))
অবশ্যই তা ((x) & (y)) == (y)
অন্যথায় এটি মাল্টিবিট মাস্কের উপর ভুল ফলাফল (পূর্ববর্তী 5
বনাম 3
) / * সমস্ত
1
হওয়া উচিত (uintmax_t)1
বা কেস কেহ অনুরূপ একটি এই ম্যাক্রো ব্যবহার করতে চায় long
বা বড় ধরনের
BITMASK_CHECK_ALL(x,y)
হিসাবে প্রয়োগ করা যেতে পারে!~((~(y))|(x))
!(~(x) & (y))
বিটগুলির নাম দেওয়ার enum
জন্য এটি কখনও কখনও মূল্যবান :
enum ThingFlags = {
ThingMask = 0x0000,
ThingFlag0 = 1 << 0,
ThingFlag1 = 1 << 1,
ThingError = 1 << 8,
}
তারপরে নামগুলি পরে ব্যবহার করুন। অর্থাৎ লিখি
thingstate |= ThingFlag1;
thingstate &= ~ThingFlag0;
if (thing & ThingError) {...}
সেট, পরিষ্কার এবং পরীক্ষা। এইভাবে আপনি আপনার বাকি কোড থেকে যাদু নম্বরগুলি গোপন রাখবেন।
তা ছাড়া আমি জেরেমির সমাধানটিকে সমর্থন করি।
clearbits()
পরিবর্তে একটি ফাংশন করতে পারে &= ~
। আপনি এই জন্য একটি এনাম ব্যবহার করছেন কেন? আমি ভেবেছিলাম সেগুলি লুকানো স্বেচ্ছাচারিত মান সহ একগুচ্ছ অনন্য ভেরিয়েবল তৈরি করার জন্য ছিল তবে আপনি প্রতিটিকে একটি নির্দিষ্ট মান নির্ধারণ করছেন। সুতরাং সুবিধা কি বনাম কেবল তাদের পরিবর্তনশীল হিসাবে সংজ্ঞায়িত?
enum
সম্পর্কিত ধ্রুবকগুলির সেটগুলির জন্য s এর ব্যবহার সি প্রোগ্রামিংয়ের ক্ষেত্রে অনেক বেশি পিছনে ফিরে যায়। আমি সন্দেহ করি যে আধুনিক সংকলকগুলির সাথে কেবল const short
সেগুলি বা যা কিছু সেগুলিই সুস্পষ্টভাবে একত্রে গোষ্ঠীযুক্ত advantage এবং আপনি যখন বিটমাস্ক ছাড়া অন্য কোনও কিছুর জন্য চান তখন আপনি স্বয়ংক্রিয় নম্বর পাবেন। অবশ্যই সি ++ এ এগুলি পৃথক প্রকারেরও গঠন করে যা আপনাকে কিছুটা অতিরিক্ত স্ট্যাটিক ত্রুটি পরীক্ষা করে তোলে।
enum ThingFlags
মান কী ThingError|ThingFlag1
?
int
। অন্তর্ভুক্ত পূর্ণসংখ্যা প্রচার বা স্বাক্ষরযুক্ত ধরণের বিটওয়াইজ অপারেশনের কারণে এটি সমস্ত ধরণের সূক্ষ্ম বাগের কারণ হতে পারে। thingstate = ThingFlag1 >> 1
উদাহরণস্বরূপ বাস্তবায়ন সংজ্ঞায়িত আচরণ প্রার্থনা করবে। thingstate = (ThingFlag1 >> x) << y
অনির্ধারিত আচরণ শুরু করতে পারে। ইত্যাদি। নিরাপদ থাকতে সর্বদা একটি স্বাক্ষরবিহীন প্রকারে কাস্ট করুন।
enum My16Bits: unsigned short { ... };
/*
** Bit set, clear, and test operations
**
** public domain snippet by Bob Stout
*/
typedef enum {ERROR = -1, FALSE, TRUE} LOGICAL;
#define BOOL(x) (!(!(x)))
#define BitSet(arg,posn) ((arg) | (1L << (posn)))
#define BitClr(arg,posn) ((arg) & ~(1L << (posn)))
#define BitTst(arg,posn) BOOL((arg) & (1L << (posn)))
#define BitFlp(arg,posn) ((arg) ^ (1L << (posn)))
ঠিক আছে, আসুন বিষয়গুলি বিশ্লেষণ করা যাক ...
আপনার এই সমস্তগুলির মধ্যে যে সমস্যাটি দেখা যাচ্ছে বলে মনে হচ্ছে তা হ'ল "(1L << (posn))"। এই সমস্তটি হ'ল একটি বিট সহ একটি মুখোশ তৈরি করা এবং এটি কোনও পূর্ণসংখ্যার ধরণের সাথে কাজ করবে। "Posn" যুক্তিটি আপনি যে অবস্থানটি চান তা নির্দিষ্ট করে। যদি posn == 0 হয়, তবে এই অভিব্যক্তিটি মূল্যায়ন করবে:
0000 0000 0000 0000 0000 0000 0000 0001 binary.
যদি posn == 8, এটি মূল্যায়ন করবে:
0000 0000 0000 0000 0000 0001 0000 0000 binary.
অন্য কথায়, এটি কেবলমাত্র নির্দিষ্ট স্থানে 1 দিয়ে একটি ক্ষেত্র তৈরি করে। কেবলমাত্র জটিল অংশটি বিটকলার () ম্যাক্রোতে রয়েছে যেখানে আমাদের 1 এর ক্ষেত্রে একটি বিট সেট করতে হবে। টিলড (~) অপারেটর দ্বারা চিহ্নিত হিসাবে একই এক্সপ্রেশনটির 1 এর পরিপূরক ব্যবহার করে এটি সম্পন্ন হয়।
একবার মুখোশটি তৈরি হয়ে গেলে এটি বিটওয়াইজ এবং (&), বা (|), এবং জোর (^) অপারেটরগুলির সাহায্যে আপনার পরামর্শ অনুসারে আর্গুমেন্টে প্রয়োগ করা হবে। যেহেতু মুখোশটি টাইপ দীর্ঘ, ম্যাক্রোগুলি চরের, শর্টস, ইনটস বা লং এর উপর ঠিক একইভাবে কাজ করবে।
মূল কথাটি হ'ল এটি একটি সম্পূর্ণ শ্রেণীর সমস্যার সাধারণ সমাধান। অবশ্যই এটি সম্ভব এবং এমনকি যথাযথ প্রতিবার যখন আপনার প্রয়োজন হ'ল স্পষ্ট মুখোশের মানগুলির সাথে এই ম্যাক্রোগুলির কোনওটির সমতুল্য পুনর্লিখন করা, তবে কেন এটি করবেন? মনে রাখবেন, ম্যাক্রো প্রতিস্থাপন প্রিপ্রোসেসরে ঘটে এবং সুতরাং উত্পন্ন কোডটি সত্যটি প্রতিফলিত করবে যে মানগুলি সংকলক দ্বারা ধ্রুবক হিসাবে বিবেচিত হয় - অর্থাত্ যখন প্রতিটি বারের দরকার হয় তখন "চাকা পুনর্নির্মাণ" করার জন্য সাধারণীকৃত ম্যাক্রোগুলি ব্যবহার করা ঠিক ততটাই দক্ষ it's বিট ম্যানিপুলেশন করুন।
অচ্ছিন্নসংশয়? এখানে কিছু পরীক্ষার কোড দেওয়া হয়েছে - আমি সম্পূর্ণ অপ্টিমাইজেশনের সাথে ওয়াটকম সি ব্যবহার করেছি এবং _ সিডেস্কেল ব্যবহার না করে ফলস্বরূপ বিশৃঙ্খলা যতটা সম্ভব পরিষ্কার হতে পারে:
---- [টেস্ট.সি] ----------------------------------------- -----------------------
#define BOOL(x) (!(!(x)))
#define BitSet(arg,posn) ((arg) | (1L << (posn)))
#define BitClr(arg,posn) ((arg) & ~(1L << (posn)))
#define BitTst(arg,posn) BOOL((arg) & (1L << (posn)))
#define BitFlp(arg,posn) ((arg) ^ (1L << (posn)))
int bitmanip(int word)
{
word = BitSet(word, 2);
word = BitSet(word, 7);
word = BitClr(word, 3);
word = BitFlp(word, 9);
return word;
}
---- [পরীক্ষা.আউট (বিচ্ছিন্ন)] -------------------------------------- ---------
Module: C:\BINK\tst.c
Group: 'DGROUP' CONST,CONST2,_DATA,_BSS
Segment: _TEXT BYTE 00000008 bytes
0000 0c 84 bitmanip_ or al,84H ; set bits 2 and 7
0002 80 f4 02 xor ah,02H ; flip bit 9 of EAX (bit 1 of AH)
0005 24 f7 and al,0f7H
0007 c3 ret
No disassembly errors
---- [ফাইনস] ------------------------------------------- ----------------------
arg
হয় long long
। 1L
সম্ভাব্য প্রশস্ততম ধরণের হওয়া দরকার, তাই (uintmax_t)1
। (আপনি হয়ত পালিয়ে যেতে পারেন 1ull
)
বিটওয়াইস অপারেটরগুলি ব্যবহার করুন: &
|
শেষ বিট সেট করতে 000b
:
foo = foo | 001b
শেষ বিটটি পরীক্ষা করতে foo
:
if ( foo & 001b ) ....
শেষ বিটটি সাফ করার জন্য foo
:
foo = foo & 110b
আমি XXXb
স্বচ্ছতার জন্য ব্যবহার করেছি । আপনি সম্ভবত বিট প্যাক করছেন এমন ডেটা স্ট্রাকচারের উপর নির্ভর করে আপনি সম্ভবত এইচএক্স প্রতিনিধিত্ব নিয়ে কাজ করবেন।
foo = foo ^ MY_MASK
foo = foo & ~MY_MASK
নবজাতকের জন্য আমি একটি উদাহরণ দিয়ে আরও কিছুটা ব্যাখ্যা করতে চাই:
উদাহরণ:
value is 0x55;
bitnum : 3rd.
&
অপারেটর ব্যবহার করা হয় বিট চেক করুন:
0101 0101
&
0000 1000
___________
0000 0000 (mean 0: False). It will work fine if the third bit is 1 (then the answer will be True)
টগল বা ফ্লিপ করুন:
0101 0101
^
0000 1000
___________
0101 1101 (Flip the third bit without affecting other bits)
|
অপারেটর: বিট সেট করুন
0101 0101
|
0000 1000
___________
0101 1101 (set the third bit without affecting other bits)
এখানে আমার প্রিয় বিট গাণিতিক ম্যাক্রো, যা কোনও ধরণের স্বাক্ষরবিহীন পূর্ণসংখ্যার অ্যারে unsigned char
পর্যন্ত কাজ করে size_t
(যা সবচেয়ে বড় টাইপ যার সাথে কাজ করার দক্ষ হওয়া উচিত):
#define BITOP(a,b,op) \
((a)[(size_t)(b)/(8*sizeof *(a))] op ((size_t)1<<((size_t)(b)%(8*sizeof *(a)))))
কিছুটা সেট করতে:
BITOP(array, bit, |=);
কিছুটা সাফ করার জন্য:
BITOP(array, bit, &=~);
কিছুটা টগল করতে:
BITOP(array, bit, ^=);
কিছুটা পরীক্ষা করার জন্য:
if (BITOP(array, bit, &)) ...
প্রভৃতি
BITOP(array, bit++, |=);
একটি লুপ ব্যবহার করা সম্ভবত কলকারী যা চায় তা করবে না।
BITCELL(a,b) |= BITMASK(a,b);
(উভয় নিতে a
একটি আর্গুমেন্ট হিসাবে আকার নির্ধারণ, কিন্তু আধুনিক মূল্যায়ন না হবে a
যেহেতু এটি কেবল উপস্থিত হয় sizeof
)।
(size_t)
কাস্ট মনে হয় কেবল কিছু স্বাক্ষরিত গণিতের সাথে বীমা করার জন্য রয়েছে %
। গেল (unsigned)
সেখানে।
(size_t)(b)/(8*sizeof *(a))
অকারণে সংকীর্ণ পারে b
বিভাজন আগে। খুব বড় বিট অ্যারে সহ কেবল একটি সমস্যা। এখনও একটি আকর্ষণীয় ম্যাক্রো।
এটি "এম্বেডেড" হিসাবে ট্যাগ হওয়ায় আমি ধরে নেব আপনি একটি মাইক্রোকন্ট্রোলার ব্যবহার করছেন। উপরের সমস্ত পরামর্শ বৈধ ও কাজের (পড়া-সংশোধন-লিখন, ইউনিয়ন, স্ট্রাইক ইত্যাদি)।
যাইহোক, অ্যাসিলোস্কোপ-ভিত্তিক ডিবাগিংয়ের সময় আমি অবাক হয়ে গেলাম যে এই পদ্ধতিগুলির সিপিইউ চক্রগুলিতে সরাসরি মাইক্রোর পোর্টসেট / পোর্টএনসিএল রেজিষ্টারে একটি মান লেখার তুলনায় যথেষ্ট পরিমাণে ওভারহেড রয়েছে যা যেখানে শক্ত লুপ / উচ্চ রয়েছে সেখানে একটি সত্য পার্থক্য করে - ফ্রিকোয়েন্সি আইএসআর এর টগলিং পিন।
অপরিচিতদের জন্য: আমার উদাহরণস্বরূপ, মাইক্রোটির একটি সাধারণ পিন-স্টেট রেজিস্টার রয়েছে PORTn যা আউটপুট পিনগুলি প্রতিফলিত করে, তাই PORTn | = BIT_TO_SET করলে সেই রেজিস্টারে একটি পঠন-পরিবর্তন-লেখার ফলস্বরূপ। তবে পোর্টটিসেট / পোর্টটিএলসিএল রেজিস্টারগুলিতে "দয়া করে এই বিট 1 করুন" (এসইটি) বা "দয়া করে এই বিটটি শূন্য করুন" (CLEAR) এবং "পিনটি একা ছেড়ে যান" এর অর্থ একটি '0' বোঝাতে একটি '1' লাগে। সুতরাং, আপনি বিট সেট করছেন বা সাফ করছেন কিনা তা নির্ভর করে দুটি বন্দর ঠিকানা দিয়ে শেষ করেছেন (সর্বদা সুবিধাজনক নয়) তবে আরও দ্রুত প্রতিক্রিয়া এবং ছোট একত্রিত কোড।
volatile
এবং তাই সংকলক এই জাতীয় নিবন্ধগুলিকে জড়িত কোডের কোনও অপ্টিমাইজেশন সম্পাদন করতে অক্ষম। সুতরাং, এই জাতীয় কোডটি বিচ্ছিন্ন করা এবং এটি কীভাবে এসেম্বলারের পর্যায়ে পরিণত হয়েছিল তা দেখার পক্ষে অনুশীলন।
বিটফিল্ড পদ্ধতির এম্বেড থাকা অঙ্গনে অন্যান্য সুবিধা রয়েছে। আপনি এমন একটি কাঠামো সংজ্ঞায়িত করতে পারেন যা কোনও নির্দিষ্ট হার্ডওয়্যার রেজিষ্টারে সরাসরি বিটগুলিতে ম্যাপ করে।
struct HwRegister {
unsigned int errorFlag:1; // one-bit flag field
unsigned int Mode:3; // three-bit mode field
unsigned int StatusCode:4; // four-bit status code
};
struct HwRegister CR3342_AReg;
বিট প্যাকিং অর্ডার সম্পর্কে আপনার সচেতন হওয়া দরকার - আমি মনে করি এটি এমএসবি প্রথম, তবে এটি বাস্তবায়ন-নির্ভর। এছাড়াও, কীভাবে আপনার সংকলক হ্যান্ডলারগুলি বাইট সীমানা অতিক্রম করে ক্ষেত্রগুলি পরীক্ষা করে
তারপরে আপনি আগের মতো পৃথক মানগুলি পড়তে, লিখতে, পরীক্ষা করতে পারবেন।
#define bit_test(x, y) ( ( ((const char*)&(x))[(y)>>3] & 0x80 >> ((y)&0x07)) >> (7-((y)&0x07) ) )
নমুনা ব্যবহার:
int main(void)
{
unsigned char arr[8] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF };
for (int ix = 0; ix < 64; ++ix)
printf("bit %d is %d\n", ix, bit_test(arr, ix));
return 0;
}
নোটস: এটি দ্রুত (এর নমনীয়তা দেওয়া হয়েছে) এবং অ-শাখা-প্রশাখার জন্য ডিজাইন করা হয়েছে। এটি সুন স্টুডিও 8 সংকলিত করার সময় দক্ষ স্পার্ক মেশিন কোডের ফলস্বরূপ; আমি এটি amd64 এ MSVC ++ 2008 ব্যবহার করেও পরীক্ষা করেছি tested বিট সেট করা ও সাফ করার জন্য অনুরূপ ম্যাক্রোগুলি তৈরি করা সম্ভব। এই সমাধানের মূল পার্থক্য এখানে অন্য অনেকের সাথে তুলনা করে হ'ল এটি যে কোনও অবস্থানের জন্য বেশ কয়েকটি ধরণের ভেরিয়েবলের জন্য কাজ করে।
স্বেচ্ছাসেবক আকারের বিটম্যাপগুলির জন্য আরও সাধারণ:
#define BITS 8
#define BIT_SET( p, n) (p[(n)/BITS] |= (0x80>>((n)%BITS)))
#define BIT_CLEAR(p, n) (p[(n)/BITS] &= ~(0x80>>((n)%BITS)))
#define BIT_ISSET(p, n) (p[(n)/BITS] & (0x80>>((n)%BITS)))
CHAR_BIT
ইতিমধ্যে সংজ্ঞায়িত limits.h
করা হয়েছে, আপনার নিজের লাগাতে হবে না BITS
(এবং বাস্তবে আপনি এটির মাধ্যমে আপনার কোডটি আরও খারাপ করে
এই প্রোগ্রামটি 0 থেকে 1 বা 1 থেকে 0 থেকে কোনও ডেটা বিট পরিবর্তন করতে হবে:
{
unsigned int data = 0x000000F0;
int bitpos = 4;
int bitvalue = 1;
unsigned int bit = data;
bit = (bit>>bitpos)&0x00000001;
int invbitvalue = 0x00000001&(~bitvalue);
printf("%x\n",bit);
if (bitvalue == 0)
{
if (bit == 0)
printf("%x\n", data);
else
{
data = (data^(invbitvalue<<bitpos));
printf("%x\n", data);
}
}
else
{
if (bit == 1)
printf("elseif %x\n", data);
else
{
data = (data|(bitvalue<<bitpos));
printf("else %x\n", data);
}
}
}
আপনি যদি কিছুটা বিড্ডলিং করছেন তবে আপনি এমন মুখোশ ব্যবহার করতে চাইতে পারেন যা পুরো জিনিসটিকে আরও ত্বরান্বিত করে তুলবে। নিম্নলিখিত ফাংশনগুলি খুব দ্রুত এবং এখনও নমনীয় (তারা কোনও আকারের বিট মানচিত্রে বিট টুইডলিংয়ের অনুমতি দেয়)।
const unsigned char TQuickByteMask[8] =
{
0x01, 0x02, 0x04, 0x08,
0x10, 0x20, 0x40, 0x80,
};
/** Set bit in any sized bit mask.
*
* @return none
*
* @param bit - Bit number.
* @param bitmap - Pointer to bitmap.
*/
void TSetBit( short bit, unsigned char *bitmap)
{
short n, x;
x = bit / 8; // Index to byte.
n = bit % 8; // Specific bit in byte.
bitmap[x] |= TQuickByteMask[n]; // Set bit.
}
/** Reset bit in any sized mask.
*
* @return None
*
* @param bit - Bit number.
* @param bitmap - Pointer to bitmap.
*/
void TResetBit( short bit, unsigned char *bitmap)
{
short n, x;
x = bit / 8; // Index to byte.
n = bit % 8; // Specific bit in byte.
bitmap[x] &= (~TQuickByteMask[n]); // Reset bit.
}
/** Toggle bit in any sized bit mask.
*
* @return none
*
* @param bit - Bit number.
* @param bitmap - Pointer to bitmap.
*/
void TToggleBit( short bit, unsigned char *bitmap)
{
short n, x;
x = bit / 8; // Index to byte.
n = bit % 8; // Specific bit in byte.
bitmap[x] ^= TQuickByteMask[n]; // Toggle bit.
}
/** Checks specified bit.
*
* @return 1 if bit set else 0.
*
* @param bit - Bit number.
* @param bitmap - Pointer to bitmap.
*/
short TIsBitSet( short bit, const unsigned char *bitmap)
{
short n, x;
x = bit / 8; // Index to byte.
n = bit % 8; // Specific bit in byte.
// Test bit (logigal AND).
if (bitmap[x] & TQuickByteMask[n])
return 1;
return 0;
}
/** Checks specified bit.
*
* @return 1 if bit reset else 0.
*
* @param bit - Bit number.
* @param bitmap - Pointer to bitmap.
*/
short TIsBitReset( short bit, const unsigned char *bitmap)
{
return TIsBitSet(bit, bitmap) ^ 1;
}
/** Count number of bits set in a bitmap.
*
* @return Number of bits set.
*
* @param bitmap - Pointer to bitmap.
* @param size - Bitmap size (in bits).
*
* @note Not very efficient in terms of execution speed. If you are doing
* some computationally intense stuff you may need a more complex
* implementation which would be faster (especially for big bitmaps).
* See (http://graphics.stanford.edu/~seander/bithacks.html).
*/
int TCountBits( const unsigned char *bitmap, int size)
{
int i, count = 0;
for (i=0; i<size; i++)
if (TIsBitSet(i, bitmap))
count++;
return count;
}
দ্রষ্টব্য, একটি 16 বিট পূর্ণসংখ্যায় বিট 'এন' সেট করতে আপনি নিম্নলিখিতটি করছেন:
TSetBit( n, &my_int);
আপনার যে বিট মানচিত্রটি পাস হবে তার বিট নম্বরটি সীমার মধ্যে রয়েছে তা নিশ্চিত করার বিষয়টি আপনার উপর নির্ভর করে। নোট করুন যে ছোট্ট এন্ডিয়ান প্রসেসরগুলির জন্য যা বাইটস, শব্দ, ডিফলস, কিউওয়ার্ডস, ইত্যাদি একে অপরের কাছে মেমরিতে সঠিকভাবে ম্যাপ করে (মূল কারণ যে ছোট্ট এন্ডিয়ান প্রসেসরগুলি বিগ-এন্ডিয়ান প্রসেসরের চেয়ে 'ভাল', আহ, আমি শিখা যুদ্ধ বোধ করছি চালু...).
এটা ব্যবহার কর:
int ToggleNthBit ( unsigned char n, int num )
{
if(num & (1 << n))
num &= ~(1 << n);
else
num |= (1 << n);
return num;
}
bitset
উত্তরের সম্প্রসারণ :
#include <iostream>
#include <bitset>
#include <string>
using namespace std;
int main() {
bitset<8> byte(std::string("10010011");
// Set Bit
byte.set(3); // 10010111
// Clear Bit
byte.reset(2); // 10010101
// Toggle Bit
byte.flip(7); // 00010101
cout << byte << endl;
return 0;
}
আপনি যদি লিনাক্স কার্নেলের সি প্রোগ্রামিং সহ এই সমস্ত অপারেশনটি সম্পাদন করতে চান তবে আমি লিনাক্স কার্নেলের স্ট্যান্ডার্ড এপিআই ব্যবহার করার পরামর্শ দিই।
Https://www.kernel.org/doc/htmldocs/kernel-api/ch02s03.html দেখুন
set_bit Atomically set a bit in memory
clear_bit Clears a bit in memory
change_bit Toggle a bit in memory
test_and_set_bit Set a bit and return its old value
test_and_clear_bit Clear a bit and return its old value
test_and_change_bit Change a bit and return its old value
test_bit Determine whether a bit is set
দ্রষ্টব্য: এখানে পুরো ক্রিয়াটি একক পদক্ষেপে ঘটে। সুতরাং এই সমস্তগুলি এমনকি এসএমপি কম্পিউটারগুলিতেও পারমাণবিক হওয়ার নিশ্চয়তা রয়েছে এবং প্রসেসরের জুড়ে সমন্বয় বজায় রাখতে দরকারী।
ভিজ্যুয়াল সি 2010, এবং সম্ভবত আরও অনেক সংকলক অন্তর্নির্মিত বুলিয়ান অপারেশনগুলির জন্য সরাসরি সমর্থন পেয়েছেন A কিছুটা বুলিয়ান এর মতো দুটি সম্ভাব্য মান রয়েছে, সুতরাং আমরা তার পরিবর্তে বুলিয়ান ব্যবহার করতে পারি - এমনকি তারা একটি বিটের চেয়েও বেশি জায়গা নেয় এমনকি এই উপস্থাপনে স্মৃতি। এটি কাজ করে, এমনকি sizeof()
অপারেটরও সঠিকভাবে কাজ করে।
bool IsGph[256], IsNotGph[256];
// Initialize boolean array to detect printable characters
for(i=0; i<sizeof(IsGph); i++) {
IsGph[i] = isgraph((unsigned char)i);
}
সুতরাং, আপনার প্রশ্নে, IsGph[i] =1
বা IsGph[i] =0
সেটিং এবং ক্লিয়ারিং বিলগুলি সহজ করুন।
ছাপানো অক্ষরগুলি খুঁজে পেতে:
// Initialize boolean array to detect UN-printable characters,
// then call function to toggle required bits true, while initializing a 2nd
// boolean array as the complement of the 1st.
for(i=0; i<sizeof(IsGph); i++) {
if(IsGph[i]) {
IsNotGph[i] = 0;
} else {
IsNotGph[i] = 1;
}
}
দ্রষ্টব্য যে এই কোড সম্পর্কে "বিশেষ" কিছুই নেই। এটি সামান্য একটি পূর্ণসংখ্যার মতো আচরণ করে - যা প্রযুক্তিগতভাবে এটি। একটি 1 বিট পূর্ণসংখ্যা যা 2 টি মান এবং 2 টি মান রাখতে পারে।
আমি একবারে এই অনুরূপটি সদৃশ loanণ রেকর্ডগুলি সন্ধান করতে ব্যবহার করেছি, যেখানে _ণ_ সংখ্যাটি ইসম কী, বিট অ্যারেতে সূচক হিসাবে 6-সংখ্যার loanণ নম্বরটি ব্যবহার করে। তীব্রভাবে দ্রুত এবং 8 মাস পরে প্রমাণিত হয়েছে যে আমরা যে মেইনফ্রেম সিস্টেমটি থেকে ডেটা পাচ্ছি তা আসলে ত্রুটিযুক্ত। বিট অ্যারেগুলির সরলতা তাদের নির্ভুলতার প্রতি আত্মবিশ্বাসকে খুব উচ্চ করে তোলে - উদাহরণস্বরূপ অনুসন্ধানের পদ্ধতির বনাম।
bool
। এমনকি int
বাস্তবায়নের জন্য ব্যবহার করা C89 সেটআপগুলির জন্য 4 বাইট এমনকিbool
এখানে সংজ্ঞায়িত হিসাবে অপারেটরগুলির মধ্যে একটি ব্যবহার করুন ।
কিছুটা সেট করতে, ব্যবহৃত হয় int x = x | 0x?;
যেখানে ?
বাইনারি আকারে বিট অবস্থান রয়েছে।
0x
হেক্সাডেসিমাল আক্ষরিক জন্য উপসর্গ, বাইনারি নয়।
আমি ব্যবহার করি এমন কিছু ম্যাক্রো এখানে রয়েছে:
SET_FLAG(Status, Flag) ((Status) |= (Flag))
CLEAR_FLAG(Status, Flag) ((Status) &= ~(Flag))
INVALID_FLAGS(ulFlags, ulAllowed) ((ulFlags) & ~(ulAllowed))
TEST_FLAGS(t,ulMask, ulBit) (((t)&(ulMask)) == (ulBit))
IS_FLAG_SET(t,ulMask) TEST_FLAGS(t,ulMask,ulMask)
IS_FLAG_CLEAR(t,ulMask) TEST_FLAGS(t,ulMask,0)
int set_nth_bit(int num, int n){
return (num | 1 << n);
}
int clear_nth_bit(int num, int n){
return (num & ~( 1 << n));
}
int toggle_nth_bit(int num, int n){
return num ^ (1 << n);
}
int check_nth_bit(int num, int n){
return num & (1 << n);
}
check_nth_bit
হতে পারে bool
।
ধরা যাক প্রথমে কিছু জিনিস
num = 55
বিটওয়াইজ অপারেশন করার জন্য পূর্ণসংখ্যা (সেট, পেতে, পরিষ্কার, টগল করুন)।
n = 4
বিটওয়াইজ অপারেশনগুলি সম্পাদনের জন্য 0 ভিত্তিক বিট অবস্থান।
nth
NUM অধিকার শিফট বিট num
, n
বার। তারপরে বিটওয়াইস এবং &
1 দিয়ে পারফর্ম করুন ।bit = (num >> n) & 1;
কিভাবে এটা কাজ করে?
0011 0111 (55 in decimal)
>> 4 (right shift 4 times)
-----------------
0000 0011
& 0000 0001 (1 in decimal)
-----------------
=> 0000 0001 (final result)
n
বার। তারপরে বিটওয়াইস বা |
অপারেশন করুন num
।num |= (1 << n); // Equivalent to; num = (1 << n) | num;
কিভাবে এটা কাজ করে?
0000 0001 (1 in decimal)
<< 4 (left shift 4 times)
-----------------
0001 0000
| 0011 0111 (55 in decimal)
-----------------
=> 0001 0000 (final result)
n
বার অর্থাত্ 1 << n
।~ (1 << n)
।&
উপরের ফলাফলটি এবং দিয়ে বিটওয়াইস এবং অপারেশন করুন num
। উপরের তিনটি পদক্ষেপ একসাথে হিসাবে লেখা যেতে পারে num & (~ (1 << n))
;num &= (~(1 << n)); // Equivalent to; num = num & (~(1 << n));
কিভাবে এটা কাজ করে?
0000 0001 (1 in decimal)
<< 4 (left shift 4 times)
-----------------
~ 0001 0000
-----------------
1110 1111
& 0011 0111 (55 in decimal)
-----------------
=> 0010 0111 (final result)
কিছুটা টগল করতে আমরা বিটওয়াইস এক্সওআর ^
অপারেটরটি ব্যবহার করি । বিটওয়াইজ এক্সওআর অপারেটর 1 টিতে মূল্যায়ন করে যদি উভয় অপারেণ্ডের সাথে সম্পর্কিত বিট আলাদা হয়, অন্যথায় 0 তে মূল্যায়ন করে।
যার অর্থ কিছুটা টগল করা যায়, আপনি টগল করতে চান এমন বিট এবং 1 দিয়ে আমাদের XOR অপারেশন করা দরকার।
num ^= (1 << n); // Equivalent to; num = num ^ (1 << n);
কিভাবে এটা কাজ করে?
0 ^ 1 => 1
,। 1 ^ 1 => 0
,। 0000 0001 (1 in decimal)
<< 4 (left shift 4 times)
-----------------
0001 0000
^ 0011 0111 (55 in decimal)
-----------------
=> 0010 0111 (final result)
প্রস্তাবিত পাঠ্য - বিটওয়াস অপারেটর অনুশীলন
আপনি কীভাবে একটি বিট সেট, সাফ এবং টগল করবেন?
মুখোশটি গঠনের চেষ্টা করার সময় একটি সাধারণ কোডিংয়ের ক্ষতি সম্পর্কে সম্বোধন করতে:
1
সর্বদা যথেষ্ট প্রশস্ত হয় না
এর number
চেয়ে বৃহত্তর ধরণের হলে কোন সমস্যাগুলি ঘটে 1
? অপরিশোধিত আচরণের (ইউবি)
x
দিকে 1 << x
পরিচালিত শিফ্টটির জন্য খুব দুর্দান্ত হতে পারে । এমনকি যদি x
খুব দুর্দান্ত না হয় তবে ~
যথেষ্ট সর্বাধিক-উল্লেখযোগ্য-বিটগুলি ফ্লিপ করতে পারে না।
// assume 32 bit int/unsigned
unsigned long long number = foo();
unsigned x = 40;
number |= (1 << x); // UB
number ^= (1 << x); // UB
number &= ~(1 << x); // UB
x = 10;
number &= ~(1 << x); // Wrong mask, not wide enough
বীমা করা 1 যথেষ্ট প্রশস্ত:
কোড ব্যবহার করতে পারে 1ull
বা পেডেন্টালি (uintmax_t)1
এবং সংকলকটিকে অনুকূল করতে দেয়।
number |= (1ull << x);
number |= ((uintmax_t)1 << x);
বা কাস্ট - যা কোডিং / পর্যালোচনা / রক্ষণাবেক্ষণ সংক্রান্ত সমস্যাগুলি কাস্টটিকে সঠিক এবং আপ টু ডেট রাখে keeping
number |= (type_of_number)1 << x;
বা ধীরে ধীরে 1
একটি গণিত অপারেশন জোর করে প্রচার করুন যা প্রকারের চেয়ে কম প্রশস্ত number
।
number |= (number*0 + 1) << x;
সবচেয়ে বিট হেরফেরের, সেরা এর সাথে কাজ করা হিসাবে স্বাক্ষরবিহীন ধরনের বদলে স্বাক্ষরিত বেশী
number |= (type_of_number)1 << x;
এবং যথাযথও নয় number |= (number*0 + 1) << x;
... বাস্তবে, এটিও নয় number |= (1ull << x);
। পজিশনে এটি করার কোনও পোর্টেবল উপায় আছে কি?
একটি সি ++ 11 টেম্প্লেটেড সংস্করণ (একটি শিরোনামে দেওয়া):
namespace bit {
template <typename T1, typename T2> inline void set (T1 &variable, T2 bit) {variable |= ((T1)1 << bit);}
template <typename T1, typename T2> inline void clear(T1 &variable, T2 bit) {variable &= ~((T1)1 << bit);}
template <typename T1, typename T2> inline void flip (T1 &variable, T2 bit) {variable ^= ((T1)1 << bit);}
template <typename T1, typename T2> inline bool test (T1 &variable, T2 bit) {return variable & ((T1)1 << bit);}
}
namespace bitmask {
template <typename T1, typename T2> inline void set (T1 &variable, T2 bits) {variable |= bits;}
template <typename T1, typename T2> inline void clear(T1 &variable, T2 bits) {variable &= ~bits;}
template <typename T1, typename T2> inline void flip (T1 &variable, T2 bits) {variable ^= bits;}
template <typename T1, typename T2> inline bool test_all(T1 &variable, T2 bits) {return ((variable & bits) == bits);}
template <typename T1, typename T2> inline bool test_any(T1 &variable, T2 bits) {return variable & bits;}
}
;
আপনার ফাংশন সংজ্ঞা অনুসারে আপনি কেন ?)
(variable & bits == bits)
?
((variable & bits) == bits)
std::bitset
মধ্যে C ++ 11
এই প্রোগ্রামটি @ জেরেমির উপরের সমাধানের ভিত্তিতে তৈরি। কেউ চাইলে দ্রুত চারপাশে খেলতে পারেন।
public class BitwiseOperations {
public static void main(String args[]) {
setABit(0, 4); // set the 4th bit, 0000 -> 1000 [8]
clearABit(16, 5); // clear the 5th bit, 10000 -> 00000 [0]
toggleABit(8, 4); // toggle the 4th bit, 1000 -> 0000 [0]
checkABit(8,4); // check the 4th bit 1000 -> true
}
public static void setABit(int input, int n) {
input = input | ( 1 << n-1);
System.out.println(input);
}
public static void clearABit(int input, int n) {
input = input & ~(1 << n-1);
System.out.println(input);
}
public static void toggleABit(int input, int n) {
input = input ^ (1 << n-1);
System.out.println(input);
}
public static void checkABit(int input, int n) {
boolean isSet = ((input >> n-1) & 1) == 1;
System.out.println(isSet);
}
}
Output :
8
0
0
true
এন বিট পরিবর্তন করতে সি ভাষায় এই ফাংশনগুলির মধ্যে একটি ব্যবহার করে দেখুন:
char bitfield;
// Start at 0th position
void chang_n_bit(int n, int value)
{
bitfield = (bitfield | (1 << n)) & (~( (1 << n) ^ (value << n) ));
}
অথবা
void chang_n_bit(int n, int value)
{
bitfield = (bitfield | (1 << n)) & ((value << n) | ((~0) ^ (1 << n)));
}
অথবা
void chang_n_bit(int n, int value)
{
if(value)
bitfield |= 1 << n;
else
bitfield &= ~0 ^ (1 << n);
}
char get_n_bit(int n)
{
return (bitfield & (1 << n)) ? 1 : 0;
}
value << n
অপরিবর্তিত আচরণের কারণ হতে পারে