ඔබ ටිකක් සකසන්නේ කෙසේද, පැහැදිලි කරන්නේ සහ ටොගල් කරන්නේ කෙසේද?
ඔබ ටිකක් සකසන්නේ කෙසේද, පැහැදිලි කරන්නේ සහ ටොගල් කරන්නේ කෙසේද?
Answers:
|
ටිකක් සැකසීමට bitwise OR operator ( ) භාවිතා කරන්න .
number |= 1UL << n;
එමඟින් n
තුන්වන කොටස සැකසෙනු ඇත number
. n
ඔබ නියම කිරීමට අවශ්ය නම්, ශුන්ය විය යුතුය 1
දක්වා මත එසේ වන bit සහ n-1
ඔබ නියම කිරීමට අවශ්ය නම්, n
වැනි ටිකක්.
වඩා පුළුල් 1ULL
නම් භාවිතා කරන්න ; a හි පළලට වඩා මාරුවීම නිර්වචනය නොකළ හැසිරීම කොතැනදැයි තක්සේරු කිරීමෙන් පසුව ප්රවර්ධනය සිදු නොවේ . අනෙක් සියලුම උදාහරණ සඳහා ද එය අදාළ වේ.number
unsigned long
1UL << n
1UL << n
long
&
ටිකක් ඉවත් කිරීමට bitwise AND operator ( ) භාවිතා කරන්න .
number &= ~(1UL << n);
n
ඒකෙන් ටිකක් ඉවත් වේවි number
. ඔබ බිට්වේස් නොට් ක්රියාකරු ( ~
) සමඟ බිට් ස්ට්රිං පෙරළා දැමිය යුතුය .
XOR ක්රියාකරු ( ^
) ටිකක් ටොගල් කිරීමට භාවිතා කළ හැකිය.
number ^= 1UL << n;
ඒ අතර වමා ඇත n
නමක ටිකක් number
.
ඔබ මෙය ඉල්ලා සිටියේ නැත, නමුත් මම එය එකතු කරමි.
ටිකක් පරික්ෂා කිරීම සඳහා, n අංකය දකුණට මාරු කරන්න, ඉන්පසු බිටුස් සහ එය:
bit = (number >> n) & 1U;
එමඟින් n
th හි බිටු අගය number
විචල්යයට ඇතුළත් bit
වේ.
මෙම සැකසීම n
එක්කෝ වන ටිකක් 1
හෝ 0
2 ගේ සහකාරියක් C ++ ක්රියාත්මක කිරීම පිළිබඳ පහත සඳහන් අත්පත් කළ හැක:
number ^= (-x ^ number) & (1UL << n);
ටිකක් n
නම් තබා ඇත x
වන 1
, හා නම් ඉවත් x
වේ 0
. x
වෙනත් වටිනාකමක් තිබේ නම් , ඔබට කුණු ලැබේ. x = !!x
එය 0 හෝ 1 දක්වා බූලියනීකරණය කරයි.
2 හි අනුපූරක නිෂේධන හැසිරීම් වලින් මෙය ස්වාධීන කිරීම සඳහා ( -1
1 හි අනුපූරකය හෝ සං sign ා / විශාලත්වය C ++ ක්රියාත්මක කිරීම මෙන් නොව සියලු බිටු සකසා ඇති තැන ), අත්සන් නොකළ නිෂේධනය භාවිතා කරන්න.
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
th බිට් එක ඉවත් කර th bit එක (x << n)
සකසනු n
ඇත x
.
පොදුවේ කේතය පිටපත් කිරීම / ඇලවීම නොකිරීමද හොඳ අදහසකි. එබැවින් බොහෝ අය පෙර සැකසුම් මැක්රෝස් ( ප්රජා විකිය තවදුරටත් පහළට පිළිතුරු දීම වැනි ) හෝ යම් ආකාරයක සංවර්ධනයක් භාවිතා කරයි.
bit = (number >> x) & 1
1
යනු int
වචනාර්ථයෙන්, අත්සන් කර ඇත. එබැවින් මෙහි සියලුම මෙහෙයුම් ක්රියාත්මක වන්නේ අත්සන් කළ අංක මත වන අතර එය ප්රමිතීන් විසින් මනාව අර්ථ දක්වා නොමැත. ප්රමිතීන් දෙදෙනෙකුගේ අනුපූරක හෝ ගණිත මාරුව සහතික නොකරන බැවින් එය භාවිතා කිරීම වඩා හොඳය 1U
.
number = number & ~(1 << n) | (x << n);
n-th බිට් x ට වෙනස් කිරීමට.
සම්මත C ++ පුස්තකාලය භාවිතා කිරීම : std::bitset<N>
.
හෝ Boost අනුවාදය: 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)
. (හිටපු වසං එසේ එය multibit පිළිබඳ නිවැරදි සත්ය ප්රතිඵලය නැවත 5
එදිරිව 3
සියලු gravediggers කිරීමට) / * ආයුබෝවන්:) * /
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 එකක් භාවිතා කරන්නේ ඇයි? සැඟවුණු අත්තනෝමතික වටිනාකමක් ඇති අද්විතීය විචල්යයන් රාශියක් නිර්මාණය කිරීම සඳහා ඒවා යැයි මම සිතුවෙමි, නමුත් ඔබ එක් එක් සඳහා නිශ්චිත අගයක් පවරයි. ඉතින් ඒවා විචල්යයන් ලෙස අර්ථ දැක්වීමට එරෙහිව ලැබෙන ප්රයෝජනය කුමක්ද?
enum
ආශ්රිත නියත කට්ටල සඳහා s භාවිතය c ක්රමලේඛනය කිරීමේදී බොහෝ back තට දිව යයි. නවීන සම්පාදකයින් සමඟ ඇති එකම වාසිය const short
හෝ ඊට වඩා පැහැදිලිවම ඒවා එකට කාණ්ඩගත වී ඇති බවට මම සැක කරමි . බිට්මාස්ක් හැර වෙනත් දෙයක් සඳහා ඔබට ඒවා අවශ්ය වූ විට ඔබට ස්වයංක්රීය අංකනය ලැබේ. ඇත්ත වශයෙන්ම c ++ වලදී, ඒවා එකිනෙකට වෙනස් වර්ගද සාදයි, එමඟින් ඔබට අමතර ස්ථිතික දෝෂ පරීක්ෂාවක් ලබා දේ.
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 == 0 නම්, මෙම ප්රකාශනය පහත පරිදි ඇගයීමට ලක් කරයි:
0000 0000 0000 0000 0000 0000 0000 0001 binary.
Posn == 8 නම්, එය පහත පරිදි ඇගයීමට ලක් කරයි:
0000 0000 0000 0000 0000 0001 0000 0000 binary.
වෙනත් වචන වලින් කිවහොත්, එය හුදෙක් නිශ්චිත ස්ථානයේ 1 සමඟ 0 හි ක්ෂේත්රයක් නිර්මාණය කරයි. එකම උපක්රමශීලී කොටස වන්නේ බිට්ක්ලර් () මැක්රෝ තුළ වන අතර එහිදී අපට 1 ක ක්ෂේත්රයක තනි බිටු 0 ක් සැකසිය යුතුය. ටිල්ඩ් (~) ක්රියාකරු විසින් දැක්වෙන එකම ප්රකාශනයේ 1 හි අනුපූරකය භාවිතා කිරීමෙන් මෙය සිදු වේ.
වෙස්මුහුණ නිර්මාණය කළ පසු එය ඔබ යෝජනා කරන ආකාරයටම බිට්වේස් සහ (&), හෝ (|) සහ xor (^) ක්රියාකරුවන් භාවිතා කරයි. වෙස් මුහුණ දිගු වන බැවින්, මැක්රෝස් චාර්, ෂෝට්ස්, ඉන්ටර්ස් හෝ ලෝන්ග්ස් මතද ක්රියා කරයි.
අවසාන කරුණ නම් මෙය සමස්ත පන්තියේ ගැටලුවලට පොදු විසඳුමකි. ඇත්ත වශයෙන්ම, ඔබට අවශ්ය සෑම අවස්ථාවකම පැහැදිලි ආවරණ අගයන් සහිත මෙම මැක්රෝස් වලින් එකකට සමාන ප්රමාණයක් නැවත ලිවීම කළ හැකි නමුත් සුදුසු වන්නේ ඇයි? මතක තබා ගන්න, සාර්ව ආදේශනය සිදුවන්නේ පූර්ව සකසනය තුළ වන අතර එම නිසා ජනනය කරන ලද කේතය මඟින් සම්පාදකයා විසින් අගයන් නියත ලෙස සලකනු ලැබේ යන කාරණය පිළිබිඹු කරයි - එනම් ඔබට අවශ්ය සෑම අවස්ථාවකම “රෝදය ප්රතිනිර්මාණය කිරීම” සඳහා සාමාන්යකරණය කරන ලද මැක්රෝස් භාවිතා කිරීම කාර්යක්ෂම වේ. ටිකක් හැසිරවීම කරන්න.
එකඟ නොවන්නේද? මෙන්න පරීක්ෂණ කේත කිහිපයක් - මම සම්පූර්ණ ප්රශස්තිකරණයෙන් හා _cdecl භාවිතා නොකර වොට්කොම් සී භාවිතා කළෙමි.
---- [TEST.C] ----------------------------------------- -----------------------
#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;
}
---- [TEST.OUT (විසුරුවා හරින ලද)] -------------------------------------- ---------
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
---- [finis] ------------------------------------------- ----------------------
arg
කියන්නේ long long
. 1L
හැකි පුළුල්ම වර්ගය විය යුතුය, එබැවින් (uintmax_t)1
. (ඔබට පැන යා හැකිය 1ull
)
බිට්වේස් ක්රියාකරුවන් භාවිතා කරන්න: &
|
අවසාන බිට් එක සැකසීමට 000b
:
foo = foo | 001b
අන්තිම බිට් පරීක්ෂා කිරීමට foo
:
if ( foo & 001b ) ....
අවසාන බිට් ඉවත් කිරීමට foo
:
foo = foo & 110b
මම XXXb
පැහැදිලිකම සඳහා භාවිතා කළෙමි . ඔබ බිටු ඇසුරුම් කරන දත්ත ව්යුහය මත පදනම්ව, ඔබ බොහෝ විට HEX නිරූපණය සමඟ වැඩ කරනු ඇත.
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
අංශයේ පෙර. ඉතා විශාල බිටු අරා සමඟ ගැටළුවක් පමණි. තවමත් සිත්ගන්නා සාර්ව.
මෙය "කාවැද්දූ" ලෙස ටැග් කර ඇති බැවින් මම හිතන්නේ ඔබ මයික්රොකොන්ට්රෝලර් භාවිතා කරන බවයි. ඉහත යෝජනා සියල්ලම වලංගු සහ වැඩ (කියවීම-වෙනස් කිරීම-ලිවීම, වෘත්තීය සමිති, ව්යුහයන් ආදිය).
කෙසේ වෙතත්, ඔසිලෝස්කෝප් මත පදනම් වූ නිදොස්කරණයක දී, මෙම ක්රමවලට සීපීයූ චක්රවල සැලකිය යුතු පොදු කාර්යයක් ඇති බව දැනගැනීමෙන් මම පුදුමයට පත් වූ අතර, මයික්රෝ හි PORTnSET / PORTnCLEAR ලේඛනයට සෘජුවම අගයක් ලිවීමට සාපේක්ෂව එය තද ලූප / ඉහළ ඇති සැබෑ වෙනසක් ඇති කරයි. අයිඑස්ආර් හි ටොගල් පයින්.
නුහුරු අය සඳහා: මගේ උදාහරණයේ දී, මයික්රෝ සතුව සාමාන්ය පින්-රාජ්ය ලේඛනයක් PORTn ඇත, එය ප්රතිදාන පයින් පිළිබිඹු කරයි, එබැවින් PORTn | = BIT_TO_SET ප්රති results ල මඟින් එම ලේඛනයට කියවීම-වෙනස් කිරීම-ලිවීම සිදු කරයි. කෙසේ වෙතත්, PORTnSET / PORTnCLEAR රෙජිස්ටාර් '1' යන්නෙන් අදහස් කරන්නේ "කරුණාකර මෙම බිට් 1 සාදන්න" (SET) හෝ "කරුණාකර මෙම බිට් ශුන්ය කරන්න" (CLEAR) සහ '0' යන්නෙන් අදහස් කරන්නේ "පින් එක තනිවම තබන්න" යන්නයි. එබැවින්, ඔබ බිට් සැකසීම හෝ ඉවත් කිරීම (සෑම විටම පහසු නොවේ) මත පදනම්ව වරාය ලිපින දෙකකින් අවසන් වේ, නමුත් වඩා වේගවත් ප්රතික්රියාවක් සහ එකලස් කරන ලද කුඩා කේතයක්.
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;
බිට් ඇසුරුම් අනුපිළිවෙල ගැන ඔබ දැනුවත් විය යුතුයි - මම හිතන්නේ එය පළමුව MSB, නමුත් මෙය ක්රියාත්මක කිරීම මත රඳා පවතී. තවද, ඔබේ සම්පාදක හසුරුවන්නන් බයිට් සීමාවන් ඉක්මවා යන ආකාරය තහවුරු කරන්න.
ඔබට පෙර මෙන් තනි අගයන් කියවීමට, ලිවීමට, පරීක්ෂා කිරීමට හැකිය.
#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 සම්පාදනය කිරීමේදී එය කාර්යක්ෂම SPARC යන්ත්ර කේතයක් ලබා දෙයි; මම එය amd64 හි MSVC ++ 2008 භාවිතා කර පරීක්ෂා කර ඇත්තෙමි. බිටු සැකසීම සහ ඉවත් කිරීම සඳහා සමාන මැක්රෝස් සෑදිය හැකිය. මෙහි ඇති වෙනත් බොහෝ අය සමඟ සසඳන විට මෙම විසඳුමේ ඇති ප්රධාන වෙනස නම් එය ඕනෑම ආකාරයක විචල්යයක ඕනෑම ස්ථානයකට වැඩ කිරීමයි.
වඩාත් සාමාන්ය, අත්තනෝමතික ප්රමාණයේ බිට්මැප් සඳහා:
#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);
ඔබ සමත් වන බිට් සිතියමේ පරාසය තුළ බිට් අංකය ඇති බව සහතික කිරීම ඔබ සතු ය. කුඩා එන්ඩියන් ප්රොසෙසර සඳහා බයිට්, වචන, ඩෝවර්ඩ්, qwords යනාදිය මතකයේ නිවැරදිව සිතියම් ගත කරන්න (කුඩා එන්ඩියන් ප්රොසෙසර විශාල-එන්ඩියන් ප්රොසෙසරවලට වඩා 'හොඳ' වීමට ප්රධාන හේතුව, අහ්, මට ගිනි යුද්ධයක් එනවා දැනේ මත...).
මෙය භාවිතා කරන්න:
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
සටහන: මෙන්න සම්පූර්ණ මෙහෙයුම එකම පියවරකින් සිදු වේ. එබැවින් මේ සියල්ල SMP පරිගණකවල පවා පරමාණුක බවට සහතික වී ඇති අතර ප්රොසෙසර හරහා සහජීවනය පවත්වා ගැනීමට ප්රයෝජනවත් වේ.
දෘශ්ය සී 2010 සහ තවත් බොහෝ සම්පාදකයින්ට බූලියන් මෙහෙයුම් සඳහා support ජු සහය ඇත. බූලියන් මෙන් මඳක් විය හැකි අගයන් දෙකක් ඇත, එබැවින් අපට ඒ වෙනුවට බූලියන් භාවිතා කළ හැකිය - ඒවා එක බිට් එකකට වඩා වැඩි ඉඩක් ගත්තද මෙම නිරූපණයේ මතකය. මෙය ක්රියා කරයි, 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;
}
}
මෙම කේතය පිළිබඳ "විශේෂ" කිසිවක් නොමැති බව සලකන්න. එය පූර්ණ සංඛ්යාවක් මෙන් සලකයි - තාක්ෂණිකව එය එයයි. අගයන් 2 ක් සහ අගයන් 2 ක් පමණක් තබා ගත හැකි බිට් 1 නිඛිලයක්.
මම වරක් මෙම ප්රවේශය භාවිතා කළේ අනුපිටපත් ණය වාර්තා සොයා ගැනීමටය, එහිදී ණය_ අංකය ISAM යතුර වන අතර ඉලක්කම් 6 ක ණය අංකය බිට් අරාවෙහි දර්ශකයක් ලෙස භාවිතා කරයි. ඉතා වේගයෙන් හා මාස 8 කට පසු, අප විසින් දත්ත ලබා ගන්නා ප්රධාන රාමු පද්ධතිය ඇත්ත වශයෙන්ම අක්රීය බව ඔප්පු විය. බිට් අරා වල සරල බව නිසා ඒවායේ නිරවද්යතාවය පිළිබඳ විශ්වාසය ඉතා ඉහළ මට්ටමක පවතී - උදාහරණයක් ලෙස සෙවීමේ ප්රවේශයකට එදිරිව.
bool
. සමහර විට int
ක්රියාත්මක කිරීමට භාවිතා කරන C89 සැකසුම් සඳහා බයිට් 4 ක් පවාbool
මෙහි අර්ථ දක්වා ඇති පරිදි එක් ක්රියාකරුවෙකු භාවිතා කරන්න .
ටිකක් කිරීම සඳහා, භාවිත int x = x | 0x?;
එහිදී ?
ද්විමය ස්වරූපයෙන් ටිකක් ස්ථාවරය වේ.
0x
යනු ද්විමය නොව ෂඩාස්රාකාරයේ වචනාර්ථය සඳහා උපසර්ගයයි.
num = 55
බිට්වේස් මෙහෙයුම් සිදු කිරීම සඳහා මුලින්ම සංඛ්යා කිහිපයක් සිතමු (සැකසීම, ලබා ගැනීම, පැහැදිලි කිරීම, ටොගල් කිරීම).
n = 4
බිට්වේස් මෙහෙයුම් සිදු කිරීම සඳහා 0 පදනම් වූ බිට් පිහිටීම.
nth
නිවැරදි මාරුව ලබා ගැනීමට num
, n
වේලාවන්. ඉන්පසු &
1 සමඟ bitwise AND කරන්න.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)
.&
ඉහත ප්රති result ලය සමඟ බිට්වේස් සහ ක්රියාකාරිත්වය සිදු කරන්න 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 දක්වා තක්සේරු කරයි.
එයින් අදහස් කරන්නේ ටිකක් ටොගල කිරීම, ඔබට ටොගල් කිරීමට අවශ්ය බිට් එක සමඟ අපි XOR මෙහෙයුම කළ යුතු අතර 1 යි.
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)
නිර්දේශිත කියවීම - බිට්වේස් ක්රියාකරු අභ්යාස
මෙන්න මම භාවිතා කරන මැක්රෝස් කිහිපයක්:
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 value, pos;
අගය - දත්ත
පොස් - සැකසීමට, පැහැදිලි කිරීමට හෝ ටොගල් කිරීමට අප උනන්දු වන බිට් එකේ පිහිටීම.
ටිකක් සකසන්න:
value = value | 1 << pos;
ටිකක් ඉවත් කරන්න:
value = value & ~(1 << pos);
ටිකක් ටොගල කරන්න:
value = value ^ 1 << pos;
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
.
ඔබ තනි බිට් එකක් සකසන්නේ කෙසේද, පැහැදිලි කරන්නේ සහ ටොගල් කරන්නේ කෙසේද?
වෙස්මුහුණ සෑදීමට උත්සාහ කරන විට පොදු කේතීකරණ අනතුරකට මුහුණ දීම:
1
සෑම විටම ප්රමාණවත් නොවේ
number
වඩා පුළුල් වර්ගයක් වන විට සිදුවන ගැටළු මොනවාද 1
?
x
මාරුව සඳහා මහත් විය හැක 1 << x
තුඩු නිර්වචනය නොකළ හැසිරීම (UB). පවා නම් 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);
හෝ වාත්තු කිරීම - වාත්තු කිරීම නිවැරදිව හා යාවත්කාලීනව තබා ගනිමින් කේතීකරණ / සමාලෝචන / නඩත්තු ගැටළු ඇති කරයි.
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 සැකසූ අනුවාදයක් (ශීර්ෂ පා put යක් තුළ තබා ඇත):
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
N බිටු වෙනස් කිරීමට C භාෂාවෙන් මෙම ශ්රිත වලින් එකක් උත්සාහ කරන්න:
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
නිර්වචනය නොකළ හැසිරීමට හේතු විය හැක