سؤال

أنا أحاول التغيير من Big Endian إلى Little Endian على مضاعفة. طريقة واحدة للذهاب هي الاستخدام

double val, tmp = 5.55;

((unsigned int *)&val)[0] = ntohl(((unsigned int *)&tmp)[1]);
((unsigned int *)&val)[1] = ntohl(((unsigned int *)&tmp)[0]);

ولكن بعد ذلك أحصل على تحذير: "إن التخلص من المؤشر الذي تم ربطه من النوع سوف يكسر القواعد الصارمة للتخلي" ولا أريد إيقاف هذا التحذير.

طريقة أخرى للذهاب هي:

#define ntohll(x) ( ( (uint64_t)(ntohl( (uint32_t)((x << 32) >> 32) )) << 32) | ntohl( ((uint32_t)(x >> 32)) ) ) 

val = (double)bswap_64(unsigned long long(tmp)); //or
val = (double)ntohll(unsigned long long(tmp));

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

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

المحلول

ربما أحاول شيئًا كهذا:

template <typename T>
void swap_endian(T& pX)
{
    // should static assert that T is a POD

    char& raw = reinterpret_cast<char&>(pX);
    std::reverse(&raw, &raw + sizeof(T));
}

قصيرة وحلوة (وغير المختبرة نسبيا). سوف يقوم المترجم بجميع التحسينات اللازمة. ما سبق محدد جيدًا لأي نوع من أنواع القرنة ، ولا يعتمد على أي تفاصيل تنفيذ.

نسخة نسخ ، عندما لا تريد تعديل الوسيطة:

template <typename T>
T swap_endian_copy(T pX)
{
    swap_endian(pX);
    return pX;
}

نصائح أخرى

هناك بعض المزالق المهمة للانتباه إليها عند التعامل مع التمثيل الثنائي للعوامات أو الزوجي.

ألا يمكنك فقط تبديلهم؟

inline unsigned long long EndianChange( double d )
{
    char ch[8];
    memcpy( ch, &d, 8 );  // Note this will be optimised out completely by pretty much every compiler.
    ch[0] ^= ch[7] ^= ch[0] ^= ch[7]; 
    ch[1] ^= ch[6] ^= ch[1] ^= ch[6];
    ch[2] ^= ch[5] ^= ch[2] ^= ch[5];
    ch[3] ^= ch[4] ^= ch[3] ^= ch[4];

    unsigned long long dRet;
    memcpy( &dRet, ch, 8 ); // Again this will get optimised out.
    return dRet;
};

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

هذا هو كل ما هناك إلى مبادلة بايت. لست متأكدًا مما تحاول القيام به ، لكن كل منصة endian كبيرة استخدمتها تستخدم نفس الترميز مثل Little-Indian فقط ترتيب البايت. سوف يعكس الرمز أعلاه ترتيب البايت لك. إلى حد كبير ، سيقوم أي مترجم ببساطة بمبادلة البايت ثم إعادة البايت المتغير المتبادل والتخلص من memcpys. هذه طريقة جيدة للتعامل مع قضايا التعرج.

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