আপনি কীভাবে একটি বিট সেট, সাফ এবং টগল করবেন?


2565

আপনি কীভাবে কিছুটা সেট, সাফ এবং টগল করবেন?



উত্তর:


3592

কিছুটা সেট করা

|কিছুটা সেট করতে বিটওয়াইস বা অপারেটর ( ) ব্যবহার করুন ।

number |= 1UL << n;

এটি এর nবিট সেট করবে numbernশূন্য হওয়া উচিত, যদি আপনি 1স্ট্রেন বিট সেট করতে চান এবং আরও কিছুক্ষণ n-1, আপনি যদি nথ্রি বিট সেট করতে চান ।

এর চেয়ে প্রশস্ত 1ULLহলে ব্যবহার করুন ; এর প্রস্থের চেয়ে বেশি দ্বারা স্থানান্তরিত করা কোথায় অনির্ধারিত আচরণ হয় তা মূল্যায়ন করার পরেও এর প্রচার হয় না । একই উদাহরণ বাকী সমস্ত উদাহরণের ক্ষেত্রেও প্রযোজ্য।numberunsigned long1UL << n1UL << nlong

কিছুটা সাফ করা হচ্ছে

&কিছুটা সাফ করতে বিটওয়াইস এবং অপারেটর ( ) ব্যবহার করুন ।

number &= ~(1UL << n);

এটি এর nবিট সাফ করবে number। আপনাকে অবশ্যই বিটওয়্যার নট অপারেটর ( ~) এর সাথে বিট স্ট্রিংটি উল্টাতে হবে এবং তারপরে এটি।

কিছুটা টগলিং করছি

এক্সওআর অপারেটর ( ^) কিছুটা টগল করতে ব্যবহৃত হতে পারে।

number ^= 1UL << n;

যে টগল হবে nএর ম বিট number

কিছুটা চেক করা হচ্ছে

আপনি এটি চেয়েছিলেন না, তবে আমি এটি যুক্ত করতেও পারি।

কিছুটা পরীক্ষা করতে, n টি ডান দিকে সরিয়ে দিন, তারপরে খানিকটা এবং এটি:

bit = (number >> n) & 1U;

এটি ভেরিয়েবলের মধ্যে nবি বিটের মান numberরাখবে bit

X তম এন বিট পরিবর্তন করা হচ্ছে

সেট nথেকে তম বিট পারেন 1বা 02 এর সম্পূরক সি ++ বাস্তবায়ন নিম্নলিখিত সঙ্গে অর্জন করা যেতে পারে:

number ^= (-x ^ number) & (1UL << n);

বিট nযদি সেট করা হবে xহয় 1, এবং যদি সাফ xহয় 0। যদি xঅন্য কিছু মূল্য আছে, আপনি আবর্জনা পেতে। x = !!xএটি 0 বা 1 এ উত্সাহিত করবে।

2 এর পরিপূরক অবহেলা আচরণকে স্বাধীন করার জন্য (যেখানে -11 এর পরিপূরক বা সাইন / মাত্রার সি ++ প্রয়োগের বিপরীতে সমস্ত বিট সেট করা আছে) স্বাক্ষরযুক্ত স্বাক্ষর ব্যবহার করুন।

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

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


127
আমি লক্ষ করতে চাই যে প্ল্যাটফর্মগুলিতে বিট সেট / ক্লিয়ার (যেমন, এভিআর মাইক্রোকন্ট্রোলার) এর স্থানীয় সমর্থন রয়েছে, সংকলকরা প্রায়শই 'মাইবাইট | = (1 << এক্স)' এর স্থানীয় বিট সেট / স্পষ্ট নির্দেশিকায় অনুবাদ করবেন যখনই এক্স থাকবে একটি ধ্রুবক, প্রাক্তন: (1 << 5), বা কনস্ট্যান্ড স্বাক্ষরিত x = 5
হারুন

52
বিট = সংখ্যা & (1 << এক্স); যদি বিট _বুল (<stdbool.h>) টাইপ না করে বিট এক্স এর মানকে বিটের মধ্যে রাখে না। অন্যথায়, বিট = !! (সংখ্যা & (1 << এক্স)); উইল ..
ক্রিস ইয়ং

23
আপনি কেন সর্বশেষটিকে পরিবর্তন করবেন নাbit = (number >> x) & 1
অ্যারোনম্যান

42
1একটি intআক্ষরিক, যা স্বাক্ষরিত হয়। সুতরাং এখানে সমস্ত ক্রিয়াকলাপ স্বাক্ষরযুক্ত সংখ্যার উপর পরিচালিত হয়, যা মানদণ্ড দ্বারা ভালভাবে সংজ্ঞায়িত হয় না। মান দুটি এর পরিপূরক বা পাটিগণিতের শিফট গ্যারান্টি দেয় না তাই এটি ব্যবহার করা ভাল 1U
সিয়ুয়ান রেন

50
আমি number = number & ~(1 << n) | (x << n);n-th বিটকে x এ পরিবর্তন করতে পছন্দ করি ।
jisli

459

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

বুস্ট সংস্করণ স্ট্যান্ডার্ড লাইব্রেরি সংকলন-সময়ের মাপের বিটসেটের সাথে তুলনা করে একটি রানটাইম আকারের বিটসেটের অনুমতি দেয় ।


34
+1 টি। স্ট্যান্ড :: বিটসেটটি "সি" থেকে ব্যবহারযোগ্য, তবে লেখক যেমন তার প্রশ্নটি "সি ++", এএফএইকি দিয়ে ট্যাগ করেছেন, আপনার উত্তরটি এখানে সবচেয়ে ভাল ... স্টাড :: ভেক্টর <বুুল> অন্য উপায়, যদি কেউ এর
উপকারিতা

23
@ অ্যান্ড্রুডোটনিচ: ভেক্টর <বুুল> হ'ল (দুর্ভাগ্যক্রমে) একটি বিশেষীকরণ যা মানগুলি বিট হিসাবে সংরক্ষণ করে। আরও তথ্যের জন্য getw.ca/publications/mill09.htm দেখুন ...
নিক্লাস

71
এটি এম্বেড থাকা অবস্থায় থাকায় কেউই এটি উল্লেখ করেনি। বেশিরভাগ এম্বেড থাকা সিস্টেমে আপনি প্লেগের মতো এসটিএল এড়ান। এবং বুস্ট সাপোর্ট সম্ভবত বেশিরভাগ এম্বেড থাকা সংকলকগুলির মধ্যে স্পষ্ট করে পাওয়া খুব বিরল পাখি।
লন্ডিন

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

37
@ লন্ডিন: আপনার বক্তব্যগুলি অত্যধিক বিস্তৃত (এভাবে তর্ক করার পক্ষে অকেজো)। আমি নিশ্চিত যে পরিস্থিতিগুলি সত্য বলে আমি খুঁজে পেতে পারি। এটি আমার প্রাথমিক পয়েন্টটি পরিবর্তন করে না। এম্বেড থাকা সিস্টেমে উভয় শ্রেণিই পুরোপুরি সূক্ষ্ম (এবং আমি জানি যে তারা ব্যবহৃত হয়)। এম্বেড থাকা সিস্টেমে এসটিএল / বুস্ট ব্যবহার না করা সম্পর্কে আপনার প্রাথমিক বিষয়টিও ভুল। আমি নিশ্চিত যে এমন সিস্টেম রয়েছে যা সেগুলি ব্যবহার করে না এবং এমনকি যে সিস্টেমগুলি তাদের ব্যবহার করে সেগুলি ন্যায়বিচারের সাথে ব্যবহার করা হয় তবে সেগুলি ব্যবহার করা হয় না তা বলা ঠিক ঠিক নয় (কারণ সিস্টেমগুলি রয়েছে যা তারা ব্যবহৃত হয়েছিল)।
মার্টিন ইয়র্ক

248

অন্য বিকল্পটি হ'ল বিট ক্ষেত্রগুলি ব্যবহার করা:

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

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


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

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

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

4
@ এন্ডোলিথ: এটি ভাল ধারণা হবে না। আপনি এটি কাজ করতে পারেন, তবে এটি অগত্যা কোনও পৃথক প্রসেসরের, বা অন্য কোনও সংকলক বা এমনকি একই সংকলকটির পরবর্তী প্রকাশে পোর্টেবল হবে না।
ফেরুকসিও

3
@ ইয়াস্কি এবং ফের্রুসিও এই পদ্ধতির জন্য একটি আকারের () বিভিন্ন উত্তর পেয়েছে কেবলমাত্র সংস্থাগুলি জুড়ে নয়, হার্ডওয়্যার জুড়ে সামঞ্জস্যের সমস্যাগুলি চিত্রিত করা উচিত। আমরা মাঝে মাঝে নিজেকে বোকা বানা করি যে আমরা ভাষা বা সংজ্ঞায়িত রানটাইমগুলির সাহায্যে এই সমস্যাগুলি সমাধান করেছি তবে এটি 'আমার मशीनটিতে কাজ করবে?' এ আসলেই নেমে আসে। আপনি এম্বেড করা ছেলেরা আমার শ্রদ্ধা (এবং সহানুভূতি) আছে।
কেলি এস ফরাসী

181

আমি বিট সেট এবং সাফ হ্যান্ডেল করতে একটি শিরোনাম ফাইলে সংজ্ঞায়িত ম্যাক্রোগুলি ব্যবহার করি:

/* 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))

17
উহ আমি বুঝতে পারি এটি একটি 5 বছরের পুরানো পোস্ট তবে এই ম্যাক্রোগুলির কোনওটিতে কোনও যুক্তির সদৃশ নেই, ড্যান
রবার্ট কেলি

11
BITMASK_CHECK(x,y) ((x) & (y))অবশ্যই তা ((x) & (y)) == (y)অন্যথায় এটি মাল্টিবিট মাস্কের উপর ভুল ফলাফল (পূর্ববর্তী 5বনাম 3) / * সমস্ত
গ্রাভিডিজারকে

7
1হওয়া উচিত (uintmax_t)1বা কেস কেহ অনুরূপ একটি এই ম্যাক্রো ব্যবহার করতে চায় longবা বড় ধরনের
এম এম

2
BITMASK_CHECK_ALL(x,y)হিসাবে প্রয়োগ করা যেতে পারে!~((~(y))|(x))
Handy999

3
@ হ্যান্ডি ৯৯৯, ডি মরগানের আইন প্রয়োগ এবং পুনরায় ব্যবস্থা করার পরে কেন তা কার্যকর হয় তা দেখতে কিছুটা সহজ!(~(x) & (y))
তাভিয়ান বার্নেস

114

বিটগুলির নাম দেওয়ার enumজন্য এটি কখনও কখনও মূল্যবান :

enum ThingFlags = {
  ThingMask  = 0x0000,
  ThingFlag0 = 1 << 0,
  ThingFlag1 = 1 << 1,
  ThingError = 1 << 8,
}

তারপরে নামগুলি পরে ব্যবহার করুন। অর্থাৎ লিখি

thingstate |= ThingFlag1;
thingstate &= ~ThingFlag0;
if (thing & ThingError) {...}

সেট, পরিষ্কার এবং পরীক্ষা। এইভাবে আপনি আপনার বাকি কোড থেকে যাদু নম্বরগুলি গোপন রাখবেন।

তা ছাড়া আমি জেরেমির সমাধানটিকে সমর্থন করি।


1
পর্যায়ক্রমে আপনি clearbits()পরিবর্তে একটি ফাংশন করতে পারে &= ~। আপনি এই জন্য একটি এনাম ব্যবহার করছেন কেন? আমি ভেবেছিলাম সেগুলি লুকানো স্বেচ্ছাচারিত মান সহ একগুচ্ছ অনন্য ভেরিয়েবল তৈরি করার জন্য ছিল তবে আপনি প্রতিটিকে একটি নির্দিষ্ট মান নির্ধারণ করছেন। সুতরাং সুবিধা কি বনাম কেবল তাদের পরিবর্তনশীল হিসাবে সংজ্ঞায়িত?
এন্ডোলিথ

4
@endolith: enumসম্পর্কিত ধ্রুবকগুলির সেটগুলির জন্য s এর ব্যবহার সি প্রোগ্রামিংয়ের ক্ষেত্রে অনেক বেশি পিছনে ফিরে যায়। আমি সন্দেহ করি যে আধুনিক সংকলকগুলির সাথে কেবল const shortসেগুলি বা যা কিছু সেগুলিই সুস্পষ্টভাবে একত্রে গোষ্ঠীযুক্ত advantage এবং আপনি যখন বিটমাস্ক ছাড়া অন্য কোনও কিছুর জন্য চান তখন আপনি স্বয়ংক্রিয় নম্বর পাবেন। অবশ্যই সি ++ এ এগুলি পৃথক প্রকারেরও গঠন করে যা আপনাকে কিছুটা অতিরিক্ত স্ট্যাটিক ত্রুটি পরীক্ষা করে তোলে।
dmckee --- প্রাক্তন-মডারেটর বিড়ালছানা

আপনি যদি বিটের প্রতিটি সম্ভাব্য মানের জন্য একটি ধ্রুবককে সংজ্ঞায়িত না করেন তবে আপনি অপরিজ্ঞাত এনাম স্থির হয়ে উঠবেন। উদাহরণস্বরূপ, এর enum ThingFlagsমান কী ThingError|ThingFlag1?
লুইস কলোরাডো

6
আপনি যদি এই পদ্ধতিটি ব্যবহার করেন তবে দয়া করে মনে রাখবেন যে এনাম ধ্রুবক সর্বদা স্বাক্ষরিত ধরণের থাকে int। অন্তর্ভুক্ত পূর্ণসংখ্যা প্রচার বা স্বাক্ষরযুক্ত ধরণের বিটওয়াইজ অপারেশনের কারণে এটি সমস্ত ধরণের সূক্ষ্ম বাগের কারণ হতে পারে। thingstate = ThingFlag1 >> 1উদাহরণস্বরূপ বাস্তবায়ন সংজ্ঞায়িত আচরণ প্রার্থনা করবে। thingstate = (ThingFlag1 >> x) << yঅনির্ধারিত আচরণ শুরু করতে পারে। ইত্যাদি। নিরাপদ থাকতে সর্বদা একটি স্বাক্ষরবিহীন প্রকারে কাস্ট করুন।
লন্ডিন

1
@ লন্ডিন: সি ++ 11 হিসাবে আপনি একটি অঙ্কের অন্তর্নিহিত ধরণের সেট করতে পারেন, যেমন: enum My16Bits: unsigned short { ... };
আইকেন ড্রাম

47

থেকে snip-c.zip এর bitops.h:

/*
**  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

---- [ফাইনস] ------------------------------------------- ----------------------


3
এ সম্পর্কে 2 টি জিনিস: (1) আপনার ম্যাক্রোগুলি বোঝার ক্ষেত্রে, কেউ কেউ ভুলভাবে বিশ্বাস করতে পারে যে ম্যাক্রোগুলি আসলে আর্গের মধ্যে / পরিষ্কার / ফ্লিপ বিট সেট করে, তবে কোনও অ্যাসাইনমেন্ট নেই; (২) আপনার টেস্ট.সি সম্পূর্ণ হয়নি; আমি সন্দেহ করি আপনি যদি আরও মামলা দিতেন তবে আপনি সমস্যাটি খুঁজে পান (পাঠক মহড়া)
ড্যান

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

2
এটি যদি ব্যর্থ argহয় long long1Lসম্ভাব্য প্রশস্ততম ধরণের হওয়া দরকার, তাই (uintmax_t)1। (আপনি হয়ত পালিয়ে যেতে পারেন 1ull)
এমএম

আপনি কি কোড-আকারের জন্য অনুকূলিত হন? ইন্টেল মূলধারার সিপিইউগুলিতে এই ফাংশনটি ফিরে আসার পরে আপনি এক্স বা ইএএক্স পড়ার সময় আংশিক-নিবন্ধভুক্ত স্টল পাবেন, কারণ এটি EAX এর 8-বিট উপাদানগুলি লিখেছে। (এটা এর AMD CPU- গুলি বা অন্যদের যে আংশিক রেজিস্টার পূর্ণ রেজিস্টার থেকে আলাদাভাবে নামান্তর করে না জরিমানা। Haswell / Skylake আলাদাভাবে আওয়ামী নামান্তর না, কিন্তু তারা পুনঃনামকরণ হিঃ না। )।
পিটার

37

বিটওয়াইস অপারেটরগুলি ব্যবহার করুন: & |

শেষ বিট সেট করতে 000b:

foo = foo | 001b

শেষ বিটটি পরীক্ষা করতে foo:

if ( foo & 001b ) ....

শেষ বিটটি সাফ করার জন্য foo:

foo = foo & 110b

আমি XXXbস্বচ্ছতার জন্য ব্যবহার করেছি । আপনি সম্ভবত বিট প্যাক করছেন এমন ডেটা স্ট্রাকচারের উপর নির্ভর করে আপনি সম্ভবত এইচএক্স প্রতিনিধিত্ব নিয়ে কাজ করবেন।


7
সি তে কোনও বাইনারি স্বরলিপি নেই বাইনারি পূর্ণসংখ্যার ধ্রুবকগুলি একটি মানহীন এক্সটেনশন।
লন্ডিন

কিছুটা টগল করতে এক্সওআর ব্যবহার করুন:foo = foo ^ MY_MASK
পিটার এল

সাফ করতে কোনও মাস্ককে উল্টাতে না ব্যবহার করুন:foo = foo & ~MY_MASK
পিটার এল

32

নবজাতকের জন্য আমি একটি উদাহরণ দিয়ে আরও কিছুটা ব্যাখ্যা করতে চাই:

উদাহরণ:

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)

26

এখানে আমার প্রিয় বিট গাণিতিক ম্যাক্রো, যা কোনও ধরণের স্বাক্ষরবিহীন পূর্ণসংখ্যার অ্যারে 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, &)) ...

প্রভৃতি


5
এটি পড়া ভাল তবে সম্ভাব্য পার্শ্ব প্রতিক্রিয়া সম্পর্কে সচেতন হওয়া উচিত। BITOP(array, bit++, |=);একটি লুপ ব্যবহার করা সম্ভবত কলকারী যা চায় তা করবে না।
পোড়া

প্রকৃতপক্ষে. =) এক বৈকল্পিক আপনি পছন্দ পারে 2 ম্যাক্রো, 1 সেটিকে আলাদা অ্যারের উপাদান এবং স্থানে বিট নাড়াচাড়া জন্য অন্যান্য অ্যাড্রেসিং জন্য, Ala BITCELL(a,b) |= BITMASK(a,b);(উভয় নিতে aএকটি আর্গুমেন্ট হিসাবে আকার নির্ধারণ, কিন্তু আধুনিক মূল্যায়ন না হবে aযেহেতু এটি কেবল উপস্থিত হয় sizeof)।
আর .. গিথহাব

1
@ আর .. এই উত্তরটি সত্যিই পুরানো, তবে আমি সম্ভবত এই ক্ষেত্রে কোনও ম্যাক্রোর চেয়ে কোনও ফাংশন পছন্দ করব।
পিসি লুডাইট

অপ্রাপ্তবয়স্ক: ২ য় (size_t)কাস্ট মনে হয় কেবল কিছু স্বাক্ষরিত গণিতের সাথে বীমা করার জন্য রয়েছে %। গেল (unsigned)সেখানে।
chux - মনিকা পুনরায় স্থাপন

(size_t)(b)/(8*sizeof *(a))অকারণে সংকীর্ণ পারে bবিভাজন আগে। খুব বড় বিট অ্যারে সহ কেবল একটি সমস্যা। এখনও একটি আকর্ষণীয় ম্যাক্রো।
chux - মনিকা পুনরায় ইনস্টল করুন

25

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

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

অপরিচিতদের জন্য: আমার উদাহরণস্বরূপ, মাইক্রোটির একটি সাধারণ পিন-স্টেট রেজিস্টার রয়েছে PORTn যা আউটপুট পিনগুলি প্রতিফলিত করে, তাই PORTn | = BIT_TO_SET করলে সেই রেজিস্টারে একটি পঠন-পরিবর্তন-লেখার ফলস্বরূপ। তবে পোর্টটিসেট / পোর্টটিএলসিএল রেজিস্টারগুলিতে "দয়া করে এই বিট 1 করুন" (এসইটি) বা "দয়া করে এই বিটটি শূন্য করুন" (CLEAR) এবং "পিনটি একা ছেড়ে যান" এর অর্থ একটি '0' বোঝাতে একটি '1' লাগে। সুতরাং, আপনি বিট সেট করছেন বা সাফ করছেন কিনা তা নির্ভর করে দুটি বন্দর ঠিকানা দিয়ে শেষ করেছেন (সর্বদা সুবিধাজনক নয়) তবে আরও দ্রুত প্রতিক্রিয়া এবং ছোট একত্রিত কোড।


কোডওয়ারিওরে সি ব্যবহার করে মাইক্রো ছিল কোল্ডফায়ার এমসিএফ52259। ডিসেসেমব্লার / এসএম এর দিকে তাকানো একটি দরকারী অনুশীলন কারণ এটি সিপিইউকে এমনকি সবচেয়ে বেসিক অপারেশন করতে যে সমস্ত পদক্ষেপগুলি অতিক্রম করতে হয়েছিল তা দেখায়। <br> আমরা সময়-সমালোচনামূলক লুপগুলিতে অন্যান্য সিপিইউ-হগিংয়ের নির্দেশাবলীও লক্ষ্য করেছি - ভ্যারিয়েবল = ম্যাক্স_ওয়াল করে প্রতিবারের জন্য সিপিইউ চক্রের একটি গাদা খরচ করতে হয়, যখন (var> ম্যাক_ওয়াল) var- = max_val কেবল ব্যবহার করে নির্দেশাবলী একটি দম্পতি। <br> আরও কয়েকটি কৌশল সম্পর্কে একটি ভাল গাইড এখানে: codeproject.com/Articles/6154/…
জন ইউ

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

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

24

বিটফিল্ড পদ্ধতির এম্বেড থাকা অঙ্গনে অন্যান্য সুবিধা রয়েছে। আপনি এমন একটি কাঠামো সংজ্ঞায়িত করতে পারেন যা কোনও নির্দিষ্ট হার্ডওয়্যার রেজিষ্টারে সরাসরি বিটগুলিতে ম্যাপ করে।

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;

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

তারপরে আপনি আগের মতো পৃথক মানগুলি পড়তে, লিখতে, পরীক্ষা করতে পারবেন।


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

1
@ লন্ডিন - সত্য, তবে এম্বেড করা সিস্টেম বিট-ফিডলিং (বিশেষত হার্ডওয়্যার রেজিস্টারে যা আমার উত্তরটির সাথে সম্পর্কিত) কোনওভাবেই কার্যকর পোর্টেবল হতে পারে না।
রডি

1
সম্পূর্ণ ভিন্ন সিপিইউগুলির মধ্যে নয় সম্ভবত। তবে আপনি সম্ভবত চান যে এটি সংযোজকগুলির মধ্যে এবং বিভিন্ন প্রকল্পের মধ্যে পোর্টেবল হয়। এবং প্রচুর এমবেডেড "বিট-ফিডিং" রয়েছে যা হার্ডওয়ারের সাথে মোটেই সম্পর্কিত নয় যেমন ডেটা প্রোটোকল এনকোডিং / ডিকোডিং।
লন্ডিন

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

20

স্বেচ্ছাসেবীর ধরণের ভেরিয়েবলের একটি স্বেচ্ছাসেবী স্থানে কিছুটা পরীক্ষা করুন:

#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 বিট সেট করা ও সাফ করার জন্য অনুরূপ ম্যাক্রোগুলি তৈরি করা সম্ভব। এই সমাধানের মূল পার্থক্য এখানে অন্য অনেকের সাথে তুলনা করে হ'ল এটি যে কোনও অবস্থানের জন্য বেশ কয়েকটি ধরণের ভেরিয়েবলের জন্য কাজ করে।


20

স্বেচ্ছাসেবক আকারের বিটম্যাপগুলির জন্য আরও সাধারণ:

#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)))

2
CHAR_BITইতিমধ্যে সংজ্ঞায়িত limits.hকরা হয়েছে, আপনার নিজের লাগাতে হবে না BITS(এবং বাস্তবে আপনি এটির মাধ্যমে আপনার কোডটি আরও খারাপ করে
এমএম

14

এই প্রোগ্রামটি 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);
        }
    }
}

14

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

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);

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


2
কোনও একক অপারেটরের সাথে প্রয়োগ করা যেতে পারে এমন কোনও ফাংশনের জন্য কোনও টেবিল ব্যবহার করবেন না। টিকউইকবাইটমাস্ক [এন] সমান (1 << n)। এছাড়াও, আপনার যুক্তি সংক্ষিপ্ত করা খুব খারাপ ধারণা। / এবং% আসলে বিভাজন / বিটওয়াইস নয় বরং বিভাজন হবে, কারণ 2 এর দ্বারা স্বাক্ষরিত বিভাজনটি কিছুটা পাশের সাথে প্রয়োগ করা যায় না। আপনার আর্গুমেন্টটি স্বাক্ষরবিহীন ইনট করা উচিত!
আর .. গীটহাব বন্ধ করুন ICE

এর সাথে কী লাভ? এটি কেবল কোডটি ধীর এবং পড়া আরও শক্ত করে তোলে? আমি এটির সাথে একটি সুবিধাও দেখতে পাচ্ছি না। 1u << n সি প্রোগ্রামারদের জন্য পড়া সহজ, এবং আশা করা যায় যে এটি একটি একক ক্লক টিক সিপিইউ নির্দেশিকায় অনুবাদ করা যায়। অন্যদিকে আপনার বিভাগটি প্রায় 10 টি টিককে অনুবাদ করা হবে অথবা নির্দিষ্ট আর্কিটেকচারটি বিভাগকে কতটা খারাপভাবে পরিচালনা করে তার উপর নির্ভর করে 100 টি টিক পর্যন্ত খারাপ bad বিটম্যাপ বৈশিষ্ট্যটি হিসাবে, গতিটির জন্য অনুকূলিতকরণের জন্য প্রতিটি বিট সূচককে বাইট সূচীতে অনুবাদ করে দেখার জন্য টেবিল পাওয়া আরও বুদ্ধিমান হয়ে উঠবে।
লুন্ডিন

2
বড় / ছোট এন্ডিয়ান হিসাবে, বড় এন্ডিয়ান একইভাবে পূর্ণসংখ্যা এবং কাঁচা ডেটা (উদাহরণস্বরূপ স্ট্রিংস) ম্যাপ করবে: পুরো বিটম্যাপ জুড়ে বাম থেকে ডান এমএসবি থেকে lsb। যদিও সামান্য এডিয়ানগুলি বাম থেকে ডানদিকে 7-0, 15-8, 23-18, 31-24 হিসাবে পূর্ণসংখ্যার মানচিত্র তৈরি করবে তবে কাঁচা তথ্য এখনও বাম থেকে ডান এমএসবিতে এলএসবি রয়েছে। সুতরাং আপনার নির্দিষ্ট অ্যালগরিদমের জন্য অ্যান্ডিয়ান কতটা ভাল তা সম্পূর্ণ আমার বাইরে, এটি বিপরীত বলে মনে হয়।
লন্ডিন

2
@ আর .. একটি টেবিল কার্যকর হতে পারে যদি আপনার প্লাটফর্মটি দক্ষতার সাথে বদল করতে না পারে, যেমন পুরানো মাইক্রোচিপ এমসিইউ'র মতো, তবে অবশ্যই স্যাম্পলটির বিভাগটি নিখরচুভাবে অক্ষম
জেব

12

এটা ব্যবহার কর:

int ToggleNthBit ( unsigned char n, int num )
{
    if(num & (1 << n))
        num &= ~(1 << n);
    else
        num |= (1 << n);

    return num;
}

5
ঠিক আছে, এটি অদক্ষ শাখা ব্যবহার করে।
asdf ও ডিফেন্ডার

3
@ এসডিএফ সংকলকের কাজটি সর্বাধিক দক্ষ বাইনারি আউটপুট করা, প্রোগ্রামারটির কাজ পরিষ্কার কোড লিখতে হয়
এমএম

3
এটি পরীক্ষা করে নির্দিষ্ট করা, সেট করা এবং একটি নির্দিষ্ট বিট সাফ করার ভাল প্রদর্শন ration তবে কিছুটা টগল করার জন্য এটি খুব খারাপ দৃষ্টিভঙ্গি।
বেন ভয়েগ্ট

10

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;
}

10

আপনি যদি লিনাক্স কার্নেলের সি প্রোগ্রামিং সহ এই সমস্ত অপারেশনটি সম্পাদন করতে চান তবে আমি লিনাক্স কার্নেলের স্ট্যান্ডার্ড এপিআই ব্যবহার করার পরামর্শ দিই।

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

দ্রষ্টব্য: এখানে পুরো ক্রিয়াটি একক পদক্ষেপে ঘটে। সুতরাং এই সমস্তগুলি এমনকি এসএমপি কম্পিউটারগুলিতেও পারমাণবিক হওয়ার নিশ্চয়তা রয়েছে এবং প্রসেসরের জুড়ে সমন্বয় বজায় রাখতে দরকারী।


9

ভিজ্যুয়াল সি 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 মাস পরে প্রমাণিত হয়েছে যে আমরা যে মেইনফ্রেম সিস্টেমটি থেকে ডেটা পাচ্ছি তা আসলে ত্রুটিযুক্ত। বিট অ্যারেগুলির সরলতা তাদের নির্ভুলতার প্রতি আত্মবিশ্বাসকে খুব উচ্চ করে তোলে - উদাহরণস্বরূপ অনুসন্ধানের পদ্ধতির বনাম।


std :: বিটসেটটি সত্যই বেশিরভাগ সংকলক দ্বারা বিট হিসাবে প্রয়োগ করা হয়
গ্যালেনেট

@ গালিনেট, সম্মত শিরোনাম ফাইল # অন্তর্ভুক্ত <বিসেট> এই ক্ষেত্রে একটি ভাল উত্স। এছাড়াও, যখন আপনাকে পরিবর্তনের জন্য ভেক্টরের আকার প্রয়োজন হয় তার জন্য বিশেষ শ্রেণীর ভেক্টর <বিউল>। সি ++ এসটিএল, ২ য় সংস্করণ, নিকোলাই এম জোসুটিস যথাক্রমে 650 এবং 281 পৃষ্ঠাগুলিতে এগুলি বিস্তৃতভাবে আবৃত করেছেন। সি ++ 11 স্ট্যান্ড :: বিটসেটে কয়েকটি নতুন দক্ষতা যুক্ত করেছে, আমার কাছে বিশেষ আগ্রহের বিষয়টি হ'ল নিয়ন্ত্রিত পাত্রে হ্যাশ ফাংশন। সতর্ক থাকুন জন্য ধন্যবাদ! আমি আমার মস্তিষ্কের ক্র্যাম্প মন্তব্য মুছতে চলেছি। ওয়েবে ইতিমধ্যে পর্যাপ্ত আবর্জনা রয়েছে। আমি এটিতে যুক্ত করতে চাই না।

3
এটি প্রত্যেকের জন্য কমপক্ষে একটি সম্পূর্ণ বাইট ব্যবহার করে bool। এমনকি intবাস্তবায়নের জন্য ব্যবহার করা C89 সেটআপগুলির জন্য 4 বাইট এমনকিbool
এমএম

@ ম্যাটম্যাকনাব, আপনি সঠিক সি ++ তে বুলিয়ান বাস্তবায়নের জন্য প্রয়োজনীয় প্রকারের আকারটি মান দ্বারা নির্দিষ্ট করা হয়নি। আমি বুঝতে পারি যে এই উত্তরটি কিছুক্ষণ আগে ত্রুটিযুক্ত ছিল, তবে লোকেদের আপাতত এটি কার্যকর বলে মনে হওয়ায় এটি এখানে রেখে দেওয়ার সিদ্ধান্ত নিয়েছে। যেমন এখানে আমার একটু গ্রন্থাগার ... ব্যবহার বিট অনুপস্থিত তাদের জন্য galinette এর মন্তব্য সবচেয়ে সহায়ক stackoverflow.com/a/16534995/1899861

2
@ রকেটরোয়: সম্ভবত এটি বাক্যটিকে "বিট অপারেশনস" এর উদাহরণ বলে দাবি করে এমন বাক্যটি পরিবর্তন করা উপযুক্ত।
বেন ভয়েগ্ট

6

এখানে সংজ্ঞায়িত হিসাবে অপারেটরগুলির মধ্যে একটি ব্যবহার করুন

কিছুটা সেট করতে, ব্যবহৃত হয় int x = x | 0x?;যেখানে ?বাইনারি আকারে বিট অবস্থান রয়েছে।


2
0xহেক্সাডেসিমাল আক্ষরিক জন্য উপসর্গ, বাইনারি নয়।
বেন ভয়েগ্ট

5

আমি ব্যবহার করি এমন কিছু ম্যাক্রো এখানে রয়েছে:

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)

5

পরিবর্তনশীল ব্যবহৃত

int value, pos;

মান - ডেটা পোস্ট -
বিটটির অবস্থান যা আমরা সেট করতে, পরিষ্কার করতে বা টগল করতে আগ্রহী।

কিছুটা সেট করুন:

value = value | 1 << pos;

কিছুটা সাফ করুন:

value = value & ~(1 << pos); 

কিছুটা টগল করুন:

value = value ^ 1 << pos;

5
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
জিভেরাস

@ গুরুতর হ্যাঁ এটি কলারদের অভিপ্রায়ের উপর নির্ভর করে
সাজ্জাদ হিশাইন খান

5

ধরা যাক প্রথমে কিছু জিনিস
num = 55 বিটওয়াইজ অপারেশন করার জন্য পূর্ণসংখ্যা (সেট, পেতে, পরিষ্কার, টগল করুন)।
n = 4বিটওয়াইজ অপারেশনগুলি সম্পাদনের জন্য 0 ভিত্তিক বিট অবস্থান।

কিভাবে একটি বিট পেতে?

  1. পেতে nthNUM অধিকার শিফট বিট 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)

কীভাবে কিছুটা সেট করবেন?

  1. একটি নির্দিষ্ট বিট সেট করতে। বাম শিফট 1 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)

কীভাবে কিছুটা সাফ করবেন?

  1. বাম শিফট 1, nবার অর্থাত্ 1 << n
  2. উপরের ফলাফলের সাথে বিটওয়াইস পরিপূরক সম্পাদন করুন। যাতে নবম বিটটি আনসেট হয়ে যায় এবং বিটের বিশ্রামটি সেট হয়ে যায়~ (1 << n)
  3. পরিশেষে, &উপরের ফলাফলটি এবং দিয়ে বিটওয়াইস এবং অপারেশন করুন 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 হয় 0 ^ 1 => 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)

প্রস্তাবিত পাঠ্য - বিটওয়াস অপারেটর অনুশীলন


বিস্তারিত ব্যাখ্যার জন্য ধন্যবাদ। বিটি ম্যাজিক লিঙ্কটির
চন্দ্র শেখর

4

আপনি কীভাবে একটি বিট সেট, সাফ এবং টগল করবেন?

মুখোশটি গঠনের চেষ্টা করার সময় একটি সাধারণ কোডিংয়ের ক্ষতি সম্পর্কে সম্বোধন করতে:
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);। পজিশনে এটি করার কোনও পোর্টেবল উপায় আছে কি?
chqrlie

1
@ chqrlie আইএমও, সাইন বিট সেট করা এবং শিফট সহ ইউবি বা আইডিবি ঝুঁকিপূর্ণ এড়ানোর সর্বোত্তম উপায় হ'ল স্বাক্ষরযুক্ত প্রকারের ব্যবহার । উচ্চ পোর্টেবল শিফ্ট স্বাক্ষরিত কোডটি গ্রহণযোগ্য হতে খুব সংশ্লেষিত।
chux - মনিকা 22

3

একটি সি ++ 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
pqnet

0

এই প্রোগ্রামটি @ জেরেমির উপরের সমাধানের ভিত্তিতে তৈরি। কেউ চাইলে দ্রুত চারপাশে খেলতে পারেন।

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

-2

এন বিট পরিবর্তন করতে সি ভাষায় এই ফাংশনগুলির মধ্যে একটি ব্যবহার করে দেখুন:

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