سؤال

انا املك حرف غير موقعة المخزن المؤقت، وأنا أتساءل كيف يمكنني كتابة وقراءة البتات الموقعة وغير الموقعة إلى المخزن المؤقت للبايت هذا.

في ال محرك المصدر هناك فئة اسمها bf_write, ، أي طريقتين رئيسيتين (تستخدمهما WriteString وWriteChar وWriteLong وما إلى ذلك) تستخدمان وظيفتين مسماتين WriteUBitLong و WriteSBitLong.

شكرا لك مقدما

هل كانت مفيدة؟

المحلول

إذا كان عدد البتات ثابتًا في وقت الترجمة:

#include <bitset>
...
std::bitset<100> b;
b[2]=true;

إذا لم يكن كذلك، استخدم Boost.dynamic_bitset

أو، إذا كنت يائسًا، std::vector، وهو في الواقع متجه بتات معبأ:

#include <vector>
...
std::vector<bool> b(100);
b[2]=true;

يبدو أنك تريد استخدام مكتبة تتطلب ناقلات بت معبأة في مجموعة من البايتات.دون أن أعرف بالضبط الترتيب الذي تضع به البتات، لا يمكنني إلا أن أشير إلى ما يلي:

1) من المحتمل أن يستخدم كل ما سبق ما لا يقل عن 32 بت من البتات مرتبة على الأقل->الأكثر أو الأكثر->الأقل أهمية

2) على وحدات المعالجة المركزية (Intel/AMD) الصغيرة، هذا يعني أن الذاكرة التي تشغلها مجموعة البايتات من ints قد لا تكون متوافقة مع ترتيب البتات داخل int.إذا كان "البت 0 هو lsb لـ int 0، ...البت 32 هو lsb لـ int 1، ..." فهذا هو نفسه في endian الصغير مثل "البت 0 هو lsb لـ char 0، ...البت 32 هو lsb لـ char 4 ..."، وفي هذه الحالة يمكنك فقط إرسال مؤشر إلى صفيف int إلى مؤشر إلى صفيف char

3) بافتراض أن الترتيب الأصلي للبايتات في مجموعة البت/المتجه الخاص بك ليس بالضبط ما تحتاجه المكتبة، فسيتعين عليك إما إنشاء ترتيب خاص بك يحتوي على التخطيط الذي تريده، أو نسخ نسخة إلى تخطيطها.

أ) إذا كان ترتيب البتات داخل البايت مختلفًا، فسيكون جدول البحث عن 256 إدخالًا الذي يعطي البايت مع البتات المعكوسة فعالاً.يمكنك إنشاء الجدول باستخدام روتين صغير.

ب) لعكس البايتات من endian الصغير<->الكبير:

inline void endian_swap(unsigned short& x)
{
    x = (x>>8) | 
        (x<<8);
}

inline void endian_swap(unsigned int& x)
{
    x = (x>>24) | 
        ((x<<8) & 0x00FF0000) |
        ((x>>8) & 0x0000FF00) |
        (x<<24);
}    

inline void endian_swap(unsigned long long& x)
{
    x = (x>>56) | 
        ((x<<40) & 0x00FF000000000000) |
        ((x<<24) & 0x0000FF0000000000) |
        ((x<<8)  & 0x000000FF00000000) |
        ((x>>8)  & 0x00000000FF000000) |
        ((x>>24) & 0x0000000000FF0000) |
        ((x>>40) & 0x000000000000FF00) |
        (x<<56);
}

للحصول على/تعيين جزء معين من الكلمة، مع وجود البت رقم 0 في الجزء الأقل أهمية من الكلمة 0:

typedef unsigned char block_t;
const unsigned block_bits=8;

inline void set_bit(block_t *d,unsigned i) {
  unsigned b=i/block_bits;
  unsigned bit=i-(block_bits*b); // same as i%b
  block_t &bl=d[b];
  bl|=(1<<bit); // or bit with 1 (others anded w/ 0)
}

inline void clear_bit(block_t *d,unsigned i) {
  unsigned b=i/block_bits;
  unsigned bit=i-(block_bits*b); // same as i%b
  block_t &bl=d[b];
  bl&=(~(1<<bit)); // and bit with 0 (other bits anded w/ 1)
}

inline void modify_bit(block_t *d,unsigned i,bool val) {
  if (val) set_bit(d,i) else clear_bit(d,i);
}

inline bool get_bit(block_t const* d,unsigned i) {
  unsigned b=i/block_bits;
  unsigned bit=i-(block_bits*b); // same as i%b
  return d[b]&(1<<bit);
}

من الواضح أنه إذا اختلفت قاعدة تنظيم البتات، فيجب عليك تغيير ما ورد أعلاه.

استخدام أوسع نطاق ممكن من عمليات وحدة المعالجة المركزية الخاصة بك بكفاءة حيث أن block_t هو الأفضل (لا تنس التغيير block_bits)، إلا إذا لم تنجح النهاية مع المكتبة التي تستخدمها.

نصائح أخرى

أعتقد أن بعض وحدات الماكرو كافية:

#define set_bit0(buf, i) ((buf)[(i)/8]&=~(1u<<(i)%8))
#define set_bit1(buf, i) ((buf)[(i)/8]|=1<<(i)%8)
#define get_bit(buf, i) ((buf)[(i)/8]>>(i)%8&1)

بالإضافة إلى ذلك، يمكن إجراء مبادلة endianness بطريقة أسرع.على سبيل المثال، بالنسبة لعدد صحيح 64 بت v، تقوم العمليات التالية بتبديل نهايته:

v = ((v & 0x00000000FFFFFFFFLLU) << 32) | (v >> 32);
v = ((v & 0x0000FFFF0000FFFFLLU) << 16) | ((v & 0xFFFF0000FFFF0000LLU) >> 16);
v = ((v & 0x00FF00FF00FF00FFLLU) << 8) | ((v & 0xFF00FF00FF00FF00LLU) >> 8);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top