سؤال

وأنا أحاول لتخزين كمية كبيرة من المعلومات المنطقية التي يتم تحديدها في وقت التشغيل. وكنت أتساءل ما يمكن أن يكون أفضل طريقة.

ولقد حاليا تحاول تخصيص الذاكرة باستخدام:

وpStatus = malloc((<number of data points>/8) + 1);

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

وpStatus[element]

ومما يؤسف له أن هذا لا يبدو أن تعمل بشكل جيد جدا. أولا، أنا أواجه صعوبة تهيئة الذاكرة إلى 0 قيمة عددية. ويمكن أن يتم ذلك باستخدام memset()؟ ومع ذلك، لا أعتقد أن والتأثير لماذا تحطم عند محاولة الوصول إلى pStatus[element].

وأنا أيضا لست مقتنعا تماما أن هذا النهج هو أفضل واحد ليكون باستخدام. ما أريد حقا هو أساسا قناع بت العملاق الذي يعكس مكانة القيم المنطقية. وقد فاتني شيء؟

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

المحلول

pStatus = malloc((<number of data points>/8) + 1);

وهذا لا تخصيص بايت كافية لبت الخاص بك. ومع ذلك،

pStatus[element]

وهذا يصل إلى element'th <م> بايت ، وليس قليلا. حتى عندما العنصر هو أكثر من الثامنة واحد من عدد من البتات، وكنت الحصول على قبالة نهاية صفيف المخصصة.

وأود أن تحديد عدد قليل من الوظائف المساعد

int get_bit(int element)
{
    uint byte_index = element/8;
    uint bit_index = element % 8;
    uint bit_mask = ( 1 << bit_index);

    return ((pStatus[byte_index] & bit_mask) != 0);
}

void set_bit (int element)
{
    uint byte_index = element/8;
    uint bit_index = element % 8;
    uint bit_mask = ( 1 << bit_index);

    pStatus[byte_index] |= bit_mask);
}

void clear_bit (int element)
{
    uint byte_index = element/8;
    uint bit_index = element % 8;
    uint bit_mask = ( 1 << bit_index);

    pStatus[byte_index] &= ~bit_mask;
}

و(خطأ التدقيق على مجموعة من العناصر يتغافل عن الوضوح. هل يمكن أن تجعل هذه وحدات الماكرو، أيضا)

نصائح أخرى

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

pStatus[element]

وعنصر تعالج <م> بايت ، وليس بت. إذا كنت تريد شيئا مثل:

pStatus[element/8] & (1 << (element % 8))

والصغيرة نقطة: للحصول على ذاكرة كافية لتخزين البتات N، (N / 8) + 1 بايت غير دقيقة (يمكن أن تكون واحدة كثيرة جدا)

و(N + 7) / 8 هو دائما أقل عدد، وإن كان.

حسنا، وأبسط الجواب سيكون لاستخدام calloc بدلا من malloc.

ويتم تعريف وتهيئة الذاكرة فإنه يخصص إلى الصفر، ويمكن في كثير من الأحيان تفعل ذلك باستخدام الحيل رسم الخرائط الصفحة.

وهذا سوف تأخذ الرعاية من مشكلة تهيئة الذاكرة الخاصة بك. يبدو أن عشرات الوظائف الأخرى هنا المناسبة لتناول مشكلة الفهرسة وحقيقة أنك في بعض الأحيان تخصيص بايت إضافية (يا للرعب!)، لذلك لن أكرر محتواها هنا.

وpStatus [عنصر] سوف تعطيك بايت كامل في هذا العنوان.

لتحديد عنصر معين كنت ستفعل شيئا مثل:

pStatus[element >> 3] |= 1 << (element & 7);

لإعادة تعيين عنصر:

pStatus[element >> 3] &= ~1 << (element & 7);

وولاختبار عنصر:

if (pStatus[element >> 3] & (1 << (element & 7)) != 0)

ويجب أن يكون تخصيص الأولي

pstatus = malloc((<number of data points> + 7) / 8)

وماذا كان سوف تعمل ولكن النفايات بايت أحيانا

وأنا لا يمكن إلا أن نلاحظ أن جميع الردود في C يبدو هنا أن نفترض أن البايت هو 8 بت. هذا ليس صحيحا بالضرورة في C (على الرغم من أنه بالطبع سوف يكون صحيحا على معظم الأجهزة التيار)، مما يجعل حتى هذا الافتراض في التعليمات البرمجية هو شكل سيء نوعا ما.

والطريقة الصحيحة لكتابة التعليمات البرمجية العمارة محايدة هي

#include <limits.h>

ومن ثم استخدام الماكرو CHAR_BIT أينما كنت في حاجة "عدد البتات في char".

تأكد نفسك أكثر سعادة وتحديد نوع وظائف للعمل على هذا النوع. بهذه الطريقة إذا تكتشف أن المداخل قليلا بطيئة جدا، ويمكنك تغيير وحدة الذاكرة لكل منطقية إلى بايت / كلمة / طويلة أو اعتماد هياكل البيانات متفرق / ديناميكية إذا الذاكرة حقا قضية (أي إذا مجموعات الخاص بك هي في معظمها الأصفار ، هل يمكن أن تبقى قائمة مع إحداثيات ال 1.

يمكنك كتابة التعليمات البرمجية لتكون في مأمن تماما للتغيرات في تنفيذ ناقلات بت الخاص.

وpStatus [عنصر] لا يعالج بعض الشيء. البايت المحدد الذي تحصل عليه يعتمد على نوع pStatus - وأفترض شار * أو ما يعادلها - حتى pStatus [عنصر] يحصل لك البايت element'th

.

هل يمكن memset لتعيين إلى 0، نعم.

 pStatus = malloc((<number of data points>/8) + 1);

والغرامة وهذا جزء من.

 pStatus[element]

وهنا حيث لديك مشكلة. كنت بايت عنوان، عندما تريد معالجة بت.

 pStatus[element / 8 ]  

وسوف تحصل على بايت المناسب في صفيف.

وتحتاج إلى تخصيص بايت c = malloc((N+7)/8)، ويمكنك تعيين نطة مع

 c[n/8]=((c[n/8] & ~(0x80 >> (n%8))) | (0x80>>(n%8)));

واضح مع

 c[n/8] &= ~(0x80 >> (n%8));

وواختبار مع

 if(c[n/8] & (0x80 >> (n%8))) blah();

إذا كنت لا تمانع في وجود لكتابة مغلفة، هل يمكن أيضا استخدام إما bit_set أو bit_vector من STL C ++ الصورة، يبدو أنهم (وخصوصا الأخير) قد بالضبط ما تحتاج إليه، مشفرة بالفعل، واختبارها وتعبئتها (والكثير من أجراس وصفارات).

وانها عار حقيقي أننا نفتقر إلى صراط مستقيم إلى الأمام إلى استخدام رمز C ++ في تطبيقات C (لا، وخلق المجمع ليس على التوالي إلى الأمام بالنسبة لي، ولا متعة، ويعني المزيد من العمل على المدى الطويل).

وماذا سيكون الخطأ في std::vector<bool>؟

ويدهشني أن إجابة واحدة فقط هنا تذكر CHAR_BIT. البايت هو 8 بت في كثير من الأحيان، ولكن ليس دائما.

ورمز تخصيص أنت هو الصحيح، راجع ظائف set_bit() وget_bit() الواردة في <لأ href = "https://stackoverflow.com/questions/177054/is-there-a-practical-limit-to-the-size- # 177092 "أقنعة من بت> هذه الإجابة للوصول إلى ومنطقية.

إذا تقتصر على بضع بت يمكنك بدلا من eaanon01 الحل أيضا استخدام مرفق ج المضمن من bitfield (هناك عدد قليل جدا من مناسبة حيث يمكن استخدامها، ولكن هذا من شأنه أن يكون واحدا)

لهذه الاشياء ضجيجا قليلا يمكنني recommendate: Herny الجحور "هاكر البهجة"

وومنطقية هو "أبدا" قيمة منفصلة في C. لذا قد يكون بنية من أجل الحصول على الذهاب.

وصحيح أن كنت لا تهيئة منطقة ذاكرة لذلك تحتاج إلى القيام بذلك بشكل فردي.

وهنا مثال بسيط كيف يمكنك أن تفعل ذلك مع البنيات النقابات وتتضمن التعدادات

typedef unsigned char           BYTE;
typedef unsigned short          WORD;
typedef unsigned long int       DWORD;
typedef unsigned long long int  DDWORD;
enum STATUS
{
    status0 = 0x01,
    status1 = 0x02,
    status2 = 0x04,
    status3 = 0x08,
    status4 = 0x10,
    status5 = 0x20,
    status6 = 0x40,
    status7 = 0x80,
status_group = status0 + status1 +status4
};
#define GET_STATUS( S ) ( ((status.DDBuf&(DDWORD)S)==(DDWORD)S) ? 1 : 0  )
#define SET_STATUS( S ) (  (status.DDBuf|=  (DDWORD)S) )
#define CLR_STATUS( S ) (  (status.DDBuf&= ~(DDWORD)S) )
static union {
 BYTE   BBuf[8];
 WORD   WWBuf[4];
 DWORD  DWBuf[2];
 DDWORD DDBuf;
}status;

int main(void)
{
    // Reset status bits
    status.BBuf[0] = 0;
    printf( "%d \n", GET_STATUS( status0 ) );

    SET_STATUS( status0 );
    printf( "%d \n", GET_STATUS( status0 ) );

    CLR_STATUS(status0);
    printf( "%d \n", GET_STATUS( status0 ) );
    SET_STATUS( status_group );
    printf( "%d \n", GET_STATUS( status0 ) );
    system( "pause" );
    return 0;
}

ويساعد هذا الأمل. هذا المثال يمكن التعامل مع ما يصل حتى 64 القيم المنطقية الحالة ويمكن من السهل تمديد.

ويستند هذا exapmle على شار = 8 بت عدد صحيح = 16 بت عدد صحيح طويل = 32 بت وكثافة طويل = 64 بت

واضفت الآن أيضا الدعم للجماعات الوضع.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top