2010-10-12 10 views
5

Tôi đang làm bài tập về nhà cho lớp C++ của mình. Câu hỏi tôi đang làm về đọc như sau:Tích phân Byte hoán đổi trong C++

Viết hàm nhận một ký tự ngắn chưa ký (2 byte) và hoán đổi byte. Ví dụ, nếu x = 258 (00000001 00000010) sau khi hoán đổi, x sẽ là 513 (00000010 00000001).

Đây là mã của tôi cho đến nay:

#include <iostream> 

using namespace std; 

unsigned short int ByteSwap(unsigned short int *x); 

int main() 
{ 
    unsigned short int x = 258; 
    ByteSwap(&x); 

    cout << endl << x << endl; 

    system("pause"); 
    return 0; 
} 

unsigned short int ByteSwap(unsigned short int *x) 
{ 
    long s; 
    long byte1[8], byte2[8]; 

    for (int i = 0; i < 16; i++) 
    { 
    s = (*x >> i)%2; 

    if(i < 8) 
    { 
     byte1[i] = s; 
     cout << byte1[i]; 
    } 
    if(i == 8) 
     cout << " "; 

    if(i >= 8) 
    { 
     byte2[i-8] = s; 
     cout << byte2[i]; 
    } 
    } 

    //Here I need to swap the two bytes 
    return *x; 
} 

Mã của tôi có hai vấn đề tôi hy vọng bạn có thể giúp tôi giải quyết.

  1. Đối với một số lý do cả hai byte của tôi là 01000000
  2. Tôi thực sự không chắc chắn làm thế nào tôi sẽ trao đổi các byte. Giáo viên của tôi ghi chú về thao tác bit là rất bị hỏng và khó theo dõi và không có nhiều ý nghĩa với tôi.

Cảm ơn bạn rất nhiều trước. Tôi thực sự đánh giá cao việc bạn giúp tôi.

+0

Khiếu nại về mã của bạn: 1) Tôi muốn tham khảo vượt qua ngắn nhập trực tiếp chứ không phải là một con trỏ. Như được viết, hàm của bạn cố gắng chỉnh sửa biến được truyền trong biến, điều này khá xấu xí. 2) Nếu bạn nhấn mạnh vào việc sửa đổi biến khi nó được truyền vào, tôi sẽ không bận tâm trả lại nó (điều này làm cho nó ngạc nhiên khi chức năng của bạn chỉnh sửa nó) và sẽ dùng tham chiếu thay vì truyền con trỏ. 3) Tôi muốn sử dụng các toán tử bit và chỉ sử dụng một mảng gồm hai byte ('char' hoặc' unsigned char'), thay vì lưu trữ từng bit trong một thời gian dài riêng biệt. – Brian

+0

Xem thêm một câu hỏi có liên quan: http://stackoverflow.com/questions/3991478/building-a-32bit-float-out-of-its-4-composite-bytes-c – Brian

Trả lời

19

Tôi nghĩ rằng bạn đang overcomplicating nó, nếu chúng ta giả định một đoạn ngắn gồm 2 byte (16 bit), bạn chỉ cần làm là

  • trích xuất các byte cao hibyte = (x & 0xff00) >> 8;
  • trích xuất thấp byte lobyte = (x & 0xff);
  • kết hợp chúng theo thứ tự ngược x = lobyte << 8 | hibyte;
+0

Tôi không quen với cú pháp đó. Bạn có thể cung cấp cho tôi một tham chiếu đến nó xin vui lòng? –

+2

@Rob S.: '&': Bitwise và hoạt động. '>>' và '<<': Hoạt động dịch chuyển bit. '|': Bitwise hoặc hoạt động. Đó là giải thích đầy đủ để làm cho googling nó thực sự dễ dàng. Hoặc chỉ cần đọc http://en.wikipedia.org/wiki/Bitwise_operation – Brian

1

Trong khi bạn có thể làm điều này với thao tác bit, bạn cũng có thể thực hiện mà không cần, nếu bạn muốn. Dù bằng cách nào, bạn không cần bất kỳ vòng lặp mặc dù. Để làm điều đó mà không cần thao tác bit, bạn sẽ xem short như một mảng của hai char s và trao đổi hai số char s, tương tự như cách bạn trao đổi hai mục trong khi (ví dụ) sắp xếp một mảng.

Để làm điều đó với thao tác bit, phiên bản hoán đổi về cơ bản là byte dưới được dịch chuyển sang trái 8 bit or d với nửa trên dịch chuyển sang trái 8 bit. Có thể bạn sẽ muốn coi nó là một loại unsigned, để đảm bảo nửa trên không được lấp đầy bằng một bit khi bạn thực hiện thay đổi đúng.

+0

Vì vậy, không có thao tác bit nào bạn đang nói đến typecasting ngắn vào một char và phá vỡ nó trong một nửa? Tôi không có nhiều kinh nghiệm với điều này nhưng tôi nghĩ rằng nó sẽ là thú vị để thử. –

+0

@Rob S .: Bạn thường lấy địa chỉ của nó, và chuyển nó tới con trỏ tới char, hoặc bạn có thể sử dụng một liên kết của hai kiểu ('short' và' char [2] '). Không có lý do để làm khác, tôi có thể sử dụng con trỏ. –

5

Bạn đang làm công việc khó khăn về điều đó.

Bạn chỉ trao đổi các byte. Vì vậy, việc hiểu làm thế nào để trích xuất hai giá trị byte, sau đó làm thế nào để tái lập lại cho họ những cách khác xung quanh

(bài tập về nhà để có câu trả lời đầy đủ nhất định)

EDIT: Không chắc do tại sao tôi làm phiền :) Tính hữu dụng của một câu trả lời cho một câu hỏi về bài tập về nhà được đo bằng số lượng OP (và có thể là những độc giả khác) tìm hiểu, không được tối đa hóa bằng cách trả lời câu hỏi homewortk trực tiếp ...

+0

Bạn có thể cung cấp cho tôi bất kỳ tài liệu tham khảo hoặc đọc nào về vấn đề này không? Tôi tin rằng hầu hết các vấn đề của tôi là tôi thiếu kiến ​​thức cơ bản về chủ đề này. –

+0

@Rob S.: Một cách để làm điều này là với một 'union'. Xem câu trả lời của tôi cho một ví dụ. Một cách khác để làm điều này là bằng cách đúc con trỏ xấu xí. Ví dụ.\t 'short s = 258; unsigned char tmp = (* (unsigned char *) (&s))'; Có lẽ có một cách tốt hơn. – Brian

+0

@RobS nếu bạn đang thực sự tham gia một lớp C++ phải có tài liệu lớp cho điều đó. Nếu lớp không cung cấp cho họ, hãy tìm Bạn đang hỏi một số câu hỏi rất cơ bản và không nên cần câu trả lời (ví dụ ý nghĩa của << etc) –

5

Có vẻ như bạn đang cố gắng trao đổi chúng một chút tại một thời điểm. Đó là một chút ... điên rồ.Những gì bạn cần làm là cô lập 2 byte và sau đó chỉ cần làm một số thay đổi. Hãy phá vỡ nó xuống:

uint16_t x = 258; 

uint16_t hi = (x & 0xff00); // isolate the upper byte with the AND operator 

uint16_t lo = (x & 0xff); // isolate the lower byte with the AND operator 

Bây giờ bạn chỉ cần để tái kết hợp chúng theo thứ tự ngược lại:

uint16_t y = (lo << 8); // shift the lower byte to the high position and assign it to y 
y |= (hi >> 8);   // OR in the upper half, into the low position 

Tất nhiên điều này có thể được thực hiện trong bước ít hơn. Ví dụ:

uint16_t y = (lo << 8) | (hi >> 8); 

Hoặc để trao đổi mà không sử dụng bất kỳ biến tạm thời:

uint16_t y = ((x & 0xff) << 8) | ((x & 0xff00) >> 8);  
+0

+1 đẹp, có vẻ như mọi người đều có thể gõ câu trả lời nhanh hơn và tốt hơn tôi có thể: D –

+0

Tác phẩm này và tôi thực sự đánh giá cao câu trả lời của bạn. Bạn có thể vui lòng cung cấp bất kỳ tài liệu tham khảo hoặc đọc tài liệu nào về cách hoạt động của nó hay không. Đặc biệt về '&' và '| 'nhân vật làm. Cảm ơn bạn rất nhiều lần nữa :) –

+0

Đó là các toán tử bitwise AND và OR trong C. http://en.wikipedia.org/wiki/Bitwise_operation –

0

Đây là một vấn đề:

byte2[i-8] = s; 
cout << byte2[i];//<--should be i-8 as well 

này đang gây ra một tràn bộ đệm.

Tuy nhiên, đó không phải là cách hay để thực hiện. Xem các toán tử dịch chuyển bit < < và >>.

1

Điều này cũng sẽ phù hợp với bạn.

#include <iostream> 

int main() { 
    unsigned int i = 0xCCFF; 
    std::cout << std::hex << i << std::endl; 

    i = (((i<<8) & 0xFFFF) | ((i >>8) & 0xFFFF)); // swaps the bytes 

    std::cout << std::hex << i << std::endl; 
} 
1
#include <stdio.h> 


int main() 
{ 
    unsigned short a = 258; 

    a = (a>>8)|((a&0xff)<<8); 

    printf("%d",a); 


} 
3

Ugly thực hiện đề nghị của Jerry để điều trị ngắn như một mảng của hai byte:

#include <iostream> 
typedef union mini 
{ 
    unsigned char b[2]; 
    short s; 
} micro; 
int main() 
{ 
    micro x; 
    x.s = 258; 
    unsigned char tmp = x.b[0]; 
    x.b[0] = x.b[1]; 
    x.b[1] = tmp; 
    std::cout << x.s << std::endl; 
} 
+0

Cảm ơn bạn rất nhiều vì điều này. Điều này giúp tôi rất nhiều :) –

+0

Bất kỳ lý do gì bạn tránh được 'std :: swap()'? – genpfault

+0

@genpfault: Không. – Brian

3

Dưới đây là một ví dụ trải ra để chứng minh byte bởi byte:

unsigned int swap_bytes(unsigned int original_value) 
{ 
    unsigned int new_value = 0; // Start with a known value. 
    unsigned int byte;   // Temporary variable. 

    // Copy the lowest order byte from the original to 
    // the new value: 
    byte = original_value & 0xFF; // Keep only the lowest byte from original value. 
    new_value = new_value * 0x100; // Shift one byte left to make room for a new byte. 
    new_value |= byte;    // Put the byte, from original, into new value. 

    // For the next byte, shift the original value by one byte 
    // and repeat the process: 
    original_value = original_value >> 8; // 8 bits per byte. 
    byte = original_value & 0xFF; // Keep only the lowest byte from original value. 
    new_value = new_value * 0x100; // Shift one byte left to make room for a new byte. 
    new_value |= byte;    // Put the byte, from original, into new value. 

    //... 
    return new_value; 
} 
+1

nhận xét hay –

0

Một chút cũ thời, nhưng vẫn còn một chút vui vẻ.

XOR swap: (xem How does XOR variable swapping work?)

#include <iostream> 
    #include <stdint.h> 
    int main() 
    { 
     uint16_t x = 0x1234; 
     uint8_t *a = reinterpret_cast<uint8_t*>(&x); 
     std::cout << std::hex << x << std::endl; 
     *(a+0) ^= *(a+1) ^= *(a+0) ^= *(a+1); 
     std::cout << std::hex << x << std::endl; 
    }