إذا كان لدي ثلاث قيم منفصلة يمكن أن تتناسب مع 32 بت ، هل من المنطقي استخدام UINT لتخزينها؟

StackOverflow https://stackoverflow.com/questions/3587593

سؤال

ما أعنيه هو ، قل لدي struct لتمثيل بعض البيانات ويبدو أن هذا:

struct LilStruct
{
    public readonly short A;
    public readonly byte B;
    public readonly byte C;

    public LilStruct(short a, byte b, byte c)
    {
        A = a;
        B = b;
        C = c;
    }
}

أ short و اثنان byte يمكن أن تتناسب القيم مع 32 بت. ما أتساءل هو (لأغراض المحاذاة ، والأداء ، أيا كان) إذا كان من المنطقي بالفعل تخزين هذه البيانات بالتنسيق التالي بدلاً من ذلك:

struct LilStruct
{
    private readonly uint _value;

    public LilStruct(short a, byte b, byte c)
    {
        _value = ((uint)a << 16) | ((uint)b << 8) | (uint)c;
    }

    public int A
    {
        get { return (int)(_value >> 16); }
    }

    public int B
    {
        get { return (int)(_value >> 8) & 0x000000FF; }
    }

    public int C
    {
        get { return (int)(_value & 0x000000FF); }
    }
}

هل هذا لا معنى له؟ ماذا ستكون الفوائد/العيوب؟

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

المحلول

في .NET ، عندما ستستخدم أ struct على أي حال ، يمكنك أيضًا تزيين الهيكل StructLayoutAttribute مثله:

[StructLayout(LayoutKind.Sequential, Pack=1)]
struct LilStruct
{
    public readonly short A;
    public readonly byte B;
    public readonly byte C;

    public LilStruct(short a, byte b, byte c)
    {
        A = a;
        B = b;
        C = c;
    }
}

سيكون لهذا تأثير أن الحقول يتم وضعها بالتتابع ، على سبيل المثال الحقل B سيبدأ في الإزاحة 16.

قيمة 1 ل Pack يعني أن الحقول محاذاة في byte حدود.

نصائح أخرى

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

عند التنفيذ على microdevice مع ما مجموعه 10 آلاف بايت من ذاكرة الوصول العشوائي ، قد يكون التعبئة مثل هذا يستحق ذلك لأن الذاكرة أكثر ثمينة من سرعة التنفيذ. على جهاز كمبيوتر مكتبي عادي أو حتى جهاز الهاتف المحمول ، ربما لا يستحق هذا التعبئة هذا الجهد.

يمكنك البقاء مع تعريف الهيكل الخاص بك ، وتطبيق structlayout ميزة مع structLayoutAttribute.pack قيمة 1. ولكن في الواقع ، من المحتمل أن توفر القليل من الذاكرة على حساب سرعة الوصول ، حيث لن يتم وضع البيانات بهذه الطريقة في الذاكرة بطريقة أكثر فعالية في الوصول. عادةً ما يضع المترجم الذاكرة بطريقة فعالة للوصول ولن تفسد الكثير من الذاكرة تلقائيًا.

من شأن هذا النهج على الأقل أن يبقي الكود الخاص بك أكثر فهمًا من نهج تحويل البت الذي اقترحته (والذي قد لا يزال أو لا يشبه في الواقع ما سيولده برنامج التحويل البرمجي للآلة من رمز البايت).

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

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

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