سؤال

كتبت مؤخرا بعض التعليمات البرمجية التي تستخدم نفس القصيرة غير الموقعة لتخزين قيمتين ونتيجة ومعرف، على سبيل المثال:

unsigned short data = new_id();
// result is either 0 or 1 so store it in the rightmost bit and move the id left
data = (data << 1) + get_result();
// ... later ...
// now we can print results like
printf("%u: %u\n", data & 1, data >> 1);

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

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

المحلول

bitfields. (ولكن فقط إذا كنت بحاجة حقا إلى أن تكون ضيقة على الفضاء - أي أنظمة مضمنة)؟

typedef struct id_result {
    unsigned int id : 15;
    unsigned int result : 1;
} id_result;

خلاف ذلك، نعم، استخدم بنية مع تعريفات أكثر اكتمالا وذات مغزى:

typedef uint16 IDTYPE; /* assuming uint16 exists elsewhere */

typedef struct id_result {
    IDTYPE id;
    bool result;
} id_result;

نصائح أخرى

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

أتذكر الوقت الذي كان لدى M68000 سجلات عنوان 32 بت ولكن فقط تم استخدام 24 بت منهم بالفعل. قام المبرمجون بجميع أنواع "التحسينات" لتخزين المعلومات في تلك البتات 8 الأخرى. كان الصبي وجوههم باللون الأحمر عند الإصدارات اللاحقة من الشريحة، مثل M68030، استخدم جميع البتات 32.

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

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

أقترح عليك أولا أن يقوم النظام بمعرفة ما إذا كان هناك أي تسرب للذاكرة أو ما إذا كان شخص ما تخصيص قطع كبيرة من الذاكرة، وما إلى ذلك، ثم حاول حل هذه المشكلة. إذا لم تتمكن من العثور على حل، فاكتشف أي جزء من برنامجك يأخذ معظم الذاكرة ومحاولة إعادة تصميم نموذج تخصيص الذاكرة.

بالنسبة لأولئك الذين ينصحون بإنصاف بالذاكرة مع Bitfields: نظرا لأن السنوات التي تمر بها وأجهزة الكمبيوتر تحصل على المزيد من غيغابايت، لا تزال L1 $ (الذاكرة السريعة) مجرد عدد قليل من عشرات الكيلبيت. بالنسبة لمعظم التطبيقات اليوم، يتم إنفاق غالبية الوقت في انتظار الذاكرة البطيئة للوصول إلى L1 $.

نظرا لأن الذاكرة البطيئة هي عنق الزجاجة في معظم التطبيقات، فإن الحفاظ على الذاكرة مع bitfields يمكن أن يزيد بشكل كبير من سرعة التطبيق بشكل كبير. لم يكن هذا صحيحا قبل عشرين عاما.

من المناسب كل من السراويل القصيرة في نفسك، في رأيي، المزيد من العمل والمزيد من الخطأ من استخدام الهيكل. إذا كان استخدام ذاكرة أقل مطلوب حقا، فيمكنك تحديد Bitfields مع بنية:

struct myStruct {
int data:8;
int result:8;
};

يحقق نفس نتيجة تقليل الذاكرة، مع زيادة الصيانة الشاملة للقانون.

الهياكل مع bitfields هي أكثر التنفيذ مفهومة. إذا كنت لا تستخدم هذا النهج، فيمكنك استخدام مجموعة من وثق بشكل جيد وحدات الماكرو هذه العبوة وتفكيك زوج القيمة داخل وخارج قيم 16 بت.

باستخدام الهياكل / الكائنات ليس بالضرورة أفضل أو أوضح النهج.

افترض أن لديك مجموعة من نقاط البيانات الصحيحة البسيطة ولكن يمكن حذفها أو تم تحديدها غير صالحة، إذا كنت تبحث ببساطة باسم MSB إلى علامة "لا تستخدم"، ثم كل ما تحتاجه لإضافته إلى الخوارزمية

if ( item > 0 )
   item += blah

ولكن إذا كان لديك بنية، فإن كل جزء من الحساب يحتاج الآن إلى الوصول إلى الأعضاء

if ( item.valid() ) 
   item.setValue(item.getValue() + blah);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top