2010-05-06 7 views
11

Có thể chuyển đổi float s từ lớn thành nhỏ về cuối không? Tôi có một giá trị lớn cuối cùng từ một nền tảng PowerPC mà tôi gửi qua TCP tới một tiến trình Windows (ít endian). Giá trị này là float, nhưng khi tôi memcpy giá trị vào loại float Win32 và sau đó gọi _byteswap_ulong trên giá trị đó, tôi luôn nhận được 0.0000?Chuyển đổi các giá trị float từ lớn endian sang ít endian

Tôi đang làm gì sai?

+0

hãy nhìn vào câu hỏi đó: http://stackoverflow.com/questions/1786137/c-serialization-of-the-floating-point-numbers-floats-doubles – Drakosha

+0

I * nghĩ * họ cả hai định dạng IEEE, nhưng bạn nên kiểm tra lại. –

+0

Điều gì xảy ra, nếu bạn không gọi '_byteswap_ulong'? –

Trả lời

23

chỉ đơn giản là đảo ngược bốn byte làm việc

float ReverseFloat(const float inFloat) 
{ 
    float retVal; 
    char *floatToConvert = (char*) & inFloat; 
    char *returnFloat = (char*) & retVal; 

    // swap the bytes into a temporary buffer 
    returnFloat[0] = floatToConvert[3]; 
    returnFloat[1] = floatToConvert[2]; 
    returnFloat[2] = floatToConvert[1]; 
    returnFloat[3] = floatToConvert[0]; 

    return retVal; 
} 
+0

đã làm điều đó! Cảm ơn! – Blade3

+0

Điều này sẽ phá vỡ trên gcc với tối ưu hóa do răng cưa răng cưa. Không làm điều đó, sử dụng công đoàn cho đúc như vậy. Tôi đã ở đó, tôi đã đánh nó. – Tomek

+7

Đó là mã C hoàn toàn hợp pháp và không trình biên dịch nào nên phá vỡ nó.Tôi đã thử nghiệm nó với VC6, Visual Studio 2008, Visual Studio 2010 và C++ Builder 2010. Không ai trong số những trình biên dịch phá vỡ mã này. –

1

Nó có thể được dễ dàng hơn để sử dụng ntoa và chức năng có liên quan để chuyển đổi từ mạng để lưu trữ và từ máy chủ để network..the lợi thế nó sẽ là cầm tay. Here là liên kết đến một bài viết giải thích cách thực hiện điều này.

1

Không ghi dữ liệu trực tiếp vào loại phao. Giữ nguyên dạng dữ liệu char, hoán đổi byte và rồi coi nó là phao.

7

Tôi đã tìm thấy thứ gì đó gần giống như thế này từ lâu rồi. Thật tốt cho một số cười, nhưng lại phải chịu đựng sự nguy hiểm của chính bạn. Tôi thậm chí đã không được biên dịch nó:

void * endian_swap(void * arg) 
{ 
    unsigned int n = *((int*)arg); 
    n = ((n >> 8) & 0x00ff00ff) | ((n << 8) & 0xff00ff00); 
    n = ((n >> 16) & 0x0000ffff) | ((n << 16) & 0xffff0000); 
    *arg = n; 

    return arg; 
} 
+0

Heh heh. Biết rằng sẽ được downvoted. Chỉ đăng nó cho cười khúc khích. Khi tôi phỏng vấn tại EA nhiều, nhiều năm trước, họ đã có một phiên bản mà đã làm thay đổi trong 1, 2, 4, 8, sau đó 16 bit chiều rộng và hỏi những gì nó đã làm. – Sniggerfardimungus

+0

Điều này cũng sẽ phá vỡ với tối ưu hóa vì nó phá vỡ các quy tắc bí mật nghiêm ngặt ... – Tomek

+0

Trước hết, tôi nghĩ rằng điều này khá rõ ràng rằng đây không phải là một giải trí nhỏ. Thứ hai, tôi không chắc chắn rằng các quy tắc bí danh được áp dụng. Trong khi có khả năng * arg có thể trỏ đến bộ nhớ sẽ được sở hữu bởi n, trình tối ưu hóa sẽ không thấy rằng có liên quan, vì nó không bao giờ sử dụng n lần nữa sau khi gán cho * arg. Quy tắc bí danh không có hiệu lực cho đến khi bạn thực hiện điều gì đó như: a = 5; * b = 7; c = a + (* b) ;, trong đó giá trị của c không thể tính từ giá trị được lưu trong bộ nhớ cache bởi vì gán * b có thể đã ảnh hưởng đến nó. Mặc dù tôi nên nói * ((int *) arg) = n; =] – Sniggerfardimungus

0

Giá trị này là một phao, nhưng khi tôi "memcpy" giá trị vào một loại phao win32 và sau đó gọi _byteswap_ulong trên giá trị đó, tôi luôn nhận được 0.0000?

Điều này sẽ hiệu quả. Bạn có thể đăng mã bạn có?

Tuy nhiên, nếu bạn quan tâm đến hiệu suất (có thể bạn không, trong trường hợp đó bạn có thể bỏ qua phần còn lại), có thể tránh memcpy, hoặc bằng cách tải trực tiếp vào vị trí đích và trao đổi byte ở đó, hoặc sử dụng một trao đổi mà không trao đổi trong khi sao chép.

-2

Cách tốt nhất để có được giá trị là sử dụng struct.pack/unpack.
Bạn có thể sử dụng ký tự ">" ở định dạng để cho biết các byte nằm ngược lại (lớn cuối).

from struct import unpack, pack 
sebytes = '\xc8\x00\x00\x00' 
print unpack('l', sebytes) 
bebytes = '\x00\x00\x00\xc8' 
print unpack('>l', bebytes) 

đầu ra:

(200,) 
(200,) 
+0

Không phải C++ theo thẻ câu hỏi –

3

Đây là một chức năng có thể đảo ngược thứ tự byte của bất kỳ loại.

template <typename T> 
T bswap(T val) { 
    T retVal; 
    char *pVal = (char*) &val; 
    char *pRetVal = (char*)&retVal; 
    int size = sizeof(T); 
    for(int i=0; i<size; i++) { 
     pRetVal[size-1-i] = pVal[i]; 
    } 

    return retVal; 
}