2011-02-09 13 views
5

मैं विन XP पर चल रहे एक C++ प्रोग्राम के लिए एक बाइट्सएप रूटीन लिखने की कोशिश कर रहा हूं। मैं विजुअल स्टूडियो 2008 के साथ संकलन कर रहा हूँ यह है कि मैं क्या लेकर आए हैं:बाइट्सएप को दो बार कैसे करें?

int byteswap(int v) // This is good 
{ 
    return _byteswap_ulong(v); 
} 

double byteswap(double v) // This doesn't work for some values 
{ 
    union { // This trick is first used in Quake2 source I believe :D 
     __int64 i; 
     double d; 
    } conv; 
    conv.d = v; 
    conv.i = _byteswap_uint64(conv.i); 
    return conv.d; 
} 

और परीक्षण करने के लिए एक समारोह:

 
-76.789999999988126 -76.790000000017230 0.000000000029104 
-30.499999999987718 -30.499999999994994 0.000000000007276 
 41.790000000014508  41.790000000029060 -0.000000000014552 
 90.330000000023560  90.330000000052664 -0.000000000029104 
:

void testit() { 
    double a, b, c; 
    CString str; 

    for (a = -100; a < 100; a += 0.01) { 
     b = byteswap(a); 
     c = byteswap(b); 
     if (a != c) { 
      str.Format("%15.15f %15.15f %15.15f", a, c, a - c); 
     } 
    } 
} 

मिलान नहीं इन नंबरों हो रही है

यह पढ़ने के बाद है:
How do I convert between big-endian and little-endian values in C++?
Little Endian - Big Endian Problem
आप डबल पर < < और >> उपयोग कर सकते हैं नहीं, वैसे (जब तक कि मैं गलत कर रहा हूँ?)

+1

आप स्पष्ट कर सकते हैं वास्तव में क्या भूकंप 2 में आविष्कार किया गया था? निश्चित रूप से एक ही संघ के क्षेत्र के रूप में एक डबल और int64 होने का विचार नहीं है? –

+0

क्षमा करें .. मैंने क्वैक 2 के सी को सीखा है, इसलिए मुझे यह सबसे अच्छा दिखाना पसंद है: डी मैं इसे अब पूरे स्थान पर देखता हूं। – Darrell

उत्तर

4

ठीक है की कोशिश करो, पता चला है कि वहाँ एक बेहतर तरीका है। दूसरी तरफ आपको सामान को पैक/अनपैक करने के आदेश के बारे में चिंता करने की ज़रूरत है। इस तरह से आप ऐसा नहीं करते:

// int and float 
static void swap4(void *v) 
{ 
    char in[4], out[4]; 
    memcpy(in, v, 4); 
    out[0] = in[3]; 
    out[1] = in[2]; 
    out[2] = in[1]; 
    out[3] = in[0]; 
    memcpy(v, out, 4); 
} 

// double 
static void swap8(void *v) 
{ 
    char in[8], out[8]; 
    memcpy(in, v, 8); 
    out[0] = in[7]; 
    out[1] = in[6]; 
    out[2] = in[5]; 
    out[3] = in[4]; 
    out[4] = in[3]; 
    out[5] = in[2]; 
    out[6] = in[1]; 
    out[7] = in[0]; 
    memcpy(v, out, 8); 
} 

typedef struct 
{ 
    int theint; 
    float thefloat; 
    double thedouble; 
} mystruct; 


static void swap_mystruct(void *buf) 
{ 
    mystruct *ps = (mystruct *) buf; 
    swap4(&ps->theint); 
    swap4(&ps->thefloat); 
    swap8(&ps->thedouble); 
}  

संदेश:

char buf[sizeof (mystruct)]; 
    memcpy(buf, &s, sizeof (mystruct)); 
    swap_mystruct(buf); 

Recv:

mystruct s; 
    swap_mystruct(buf); 
    memcpy(&s, buf, sizeof (mystruct)); 
6

हालांकि मुख्य स्मृति में एक double 64 बिट्स है, x86 CPUs पर डबल परिशुद्धता रजिस्टरों 80 हैं बिट्स चौड़ा इसलिए यदि आपके मूल्यों में से एक को पूरे रजिस्टर में संग्रहीत किया जाता है, लेकिन दूसरा मुख्य मेमोरी के माध्यम से एक गोल-यात्रा करता है और 64 बिट्स तक छोटा कर दिया जाता है, तो यह आपके द्वारा देखे जा रहे छोटे अंतरों को समझा सकता है।

हो सकता है कि आप अपने पते (और इसे प्रिंट करके, संकलक को इसे अनुकूलित करने से रोकने के लिए) को मुख्य स्मृति में रहने के लिए चर को मजबूर कर सकें, लेकिन मुझे यकीन नहीं है कि यह काम करने की गारंटी है।

+0

+1: मुझे लगता है कि यह यहां होता है: 'ए' एक रजिस्टर में है और 'सी' स्मृति में है, जबकि वहां वृद्धि हुई है। – mmmmmmmm

3
b = byteswap(a); 

यह एक समस्या है। बाइट्स को स्वैप करने के बाद, मान अब उचित डबल नहीं है। एफपीयू मूल्य को सामान्य करते समय इसे दोहरी पर संग्रहीत करना सूक्ष्म समस्याएं पैदा कर रहा है। आपको इसे वापस __int64 (लंबे समय तक) में स्टोर करना होगा। विधि के वापसी प्रकार को संशोधित करें।

+0

वास्तव में समझ में आता है! ठीक है, इसमें देखेंगे और आपसे वापस आ जाएंगे – Darrell

0

ठीक है की कोशिश करें, यह काम कर रहा हो गया है! हंस पासेंट सही था। उन्होंने मुझे "उचित दोहरी" टिप्पणी के साथ सोचने के लिए प्रेरित किया। तो आप एक फ्लोट को किसी अन्य फ्लोट में बाइट्सएप नहीं कर सकते हैं क्योंकि तब यह एक अनुचित प्रारूप में हो सकता है, इसलिए आपको एक चार सरणी के लिए बाइट्सएप करना होगा और वापस अनसुलझा करना होगा।

int pack(int value, char *buf) 
{ 
    union temp { 
     int value; 
     char c[4]; 
    } in, out; 
    in.value = value; 
    out.c[0] = in.c[3]; 
    out.c[1] = in.c[2]; 
    out.c[2] = in.c[1]; 
    out.c[3] = in.c[0]; 
    memcpy(buf, out.c, 4); 
    return 4; 
} 

int pack(float value, char *buf) 
{ 
    union temp { 
     float value; 
     char c[4]; 
    } in, out; 
    in.value = value; 
    out.c[0] = in.c[3]; 
    out.c[1] = in.c[2]; 
    out.c[2] = in.c[1]; 
    out.c[3] = in.c[0]; 
    memcpy(buf, out.c, 4); 
    return 4; 
} 

int pack(double value, char *buf) 
{ 
    union temp { 
     double value; 
     char c[8]; 
    } in, out; 
    in.value = value; 
    out.c[0] = in.c[7]; 
    out.c[1] = in.c[6]; 
    out.c[2] = in.c[5]; 
    out.c[3] = in.c[4]; 
    out.c[4] = in.c[3]; 
    out.c[5] = in.c[2]; 
    out.c[6] = in.c[1]; 
    out.c[7] = in.c[0]; 
    memcpy(buf, out.c, 8); 
    return 8; 
} 

int unpack(char *buf, int *value) 
{ 
    union temp { 
     int value; 
     char c[4]; 
    } in, out; 
    memcpy(in.c, buf, 4); 
    out.c[0] = in.c[3]; 
    out.c[1] = in.c[2]; 
    out.c[2] = in.c[1]; 
    out.c[3] = in.c[0]; 
    memcpy(value, &out.value, 4); 
    return 4; 
} 

int unpack(char *buf, float *value) 
{ 
    union temp { 
     float value; 
     char c[4]; 
    } in, out; 
    memcpy(in.c, buf, 4); 
    out.c[0] = in.c[3]; 
    out.c[1] = in.c[2]; 
    out.c[2] = in.c[1]; 
    out.c[3] = in.c[0]; 
    memcpy(value, &out.value, 4); 
    return 4; 
} 

int unpack(char *buf, double *value) 
{ 
    union temp { 
     double value; 
     char c[8]; 
    } in, out; 
    memcpy(in.c, buf, 8); 
    out.c[0] = in.c[7]; 
    out.c[1] = in.c[6]; 
    out.c[2] = in.c[5]; 
    out.c[3] = in.c[4]; 
    out.c[4] = in.c[3]; 
    out.c[5] = in.c[2]; 
    out.c[6] = in.c[1]; 
    out.c[7] = in.c[0]; 
    memcpy(value, &out.value, 8); 
    return 8; 
} 

और एक साधारण परीक्षण समारोह:: इस कोड मैं प्रयोग किया जाता है

typedef struct 
{ 
    int theint; 
    float thefloat; 
    double thedouble; 
} mystruct; 

void PackStruct() 
{ 
    char buf[sizeof (mystruct)]; 
    char *p; 
    p = buf; 

    mystruct foo, foo2; 
    foo.theint = 1; 
    foo.thefloat = 3.14f; 
    foo.thedouble = 400.5; 

    p += pack(foo.theint, p); 
    p += pack(foo.thefloat, p); 
    p += pack(foo.thedouble, p); 

    // Send or recv char array 

    p = buf; 
    p += unpack(p, &foo2.theint); 
    p += unpack(p, &foo2.thefloat); 
    p += unpack(p, &foo2.thedouble); 
} 

 संबंधित मुद्दे

  • कोई संबंधित समस्या नहीं^_^