2012-04-25 24 views
14

Tôi có một unsigned int số (2 byte) và tôi muốn chuyển đổi nó để unsigned char loại. Từ tìm kiếm của tôi, tôi thấy rằng hầu hết mọi người khuyên bạn nên làm như sau:C - unsigned int để unsigned char mảng chuyển đổi

unsigned int x; 
... 
unsigned char ch = (unsigned char)x; 

Phương pháp tiếp cận phù hợp? Tôi yêu cầu bởi vì unsigned char là 1 byte và chúng tôi đúc từ 2 byte dữ liệu đến 1 byte.

Để tránh mất dữ liệu, tôi muốn tạo một mảng char chưa ký [] và lưu các byte riêng lẻ vào mảng. Tôi đang mắc kẹt tại như sau:

unsigned char ch[2]; 
unsigned int num = 272; 

for(i=0; i<2; i++){ 
     // how should the individual bytes from num be saved in ch[0] and ch[1] ?? 
} 

Ngoài ra, cách chúng tôi sẽ chuyển đổi các char unsigned [2] trở lại unsigned int.

Cảm ơn rất nhiều.

+0

có thể trùng lặp của [ký tên ngắn thành byte trong C++] (http://stackoverflow.com/questi/10288109/signed-short-to-byte-in-c) –

Trả lời

16

Bạn có thể sử dụng memcpy trong trường hợp đó:

memcpy(ch, (char*)&num, 2); /* although sizeof(int) would be better */ 

Ngoài ra, làm thế nào sẽ được chuyển đổi char unsigned [2] trở lại int unsigned.

Tương tự, chỉ cần đảo ngược đối số của memcpy.

15

Làm thế nào về:

ch[0] = num & 0xFF; 
ch[1] = (num >> 8) & 0xFF; 

Các hoạt động ngược lại là trái như một bài tập.

7

Cách sử dụng công đoàn?

union { 
    unsigned int num; 
    unsigned char ch[2]; 
} theValue; 

theValue.num = 272; 
printf("The two bytes: %d and %d\n", theValue.ch[0], theValue.ch[1]); 
4

Tất nhiên, mảng ký tự đủ lớn để chứa giá trị lớn hơn phải chính xác lớn như giá trị này. Vì vậy, bạn chỉ có thể giả vờ rằng giá trị lớn này đã là một mảng ký tự:

unsigned int x = 12345678;//well, it should be just 1234. 
unsigned char* pChars; 

pChars = (unsigned char*) &x; 

pChars[0];//one byte is here 
pChars[1];//another byte here 

(Một khi bạn hiểu được những gì đang xảy ra, nó có thể được thực hiện mà không bất kỳ biến, tất cả chỉ là đúc)

+2

Nếu '12345678' khớp với' unsigned int' và 'sizeof (unsigned int) == 2', thì' CHAR_BIT' lớn hơn bình thường ;-) –

+0

Tôi đổ lỗi cho xã hội 32 bit vì đã làm hỏng tôi! –

2

Bạn chỉ cần trích xuất các byte đó bằng cách sử dụng bitwise & operator. OxFF là mặt nạ thập lục phân để trích xuất một byte. Hãy nhìn vào các hoạt động chút khác nhau ở đây - http://www.catonmat.net/blog/low-level-bit-hacks-you-absolutely-must-know/

Một chương trình ví dụ là như sau:

#include <stdio.h> 

int main() 
{ 
    unsigned int i = 0x1122; 
    unsigned char c[2]; 

    c[0] = i & 0xFF; 
    c[1] = (i>>8) & 0xFF; 

    printf("c[0] = %x \n", c[0]); 
    printf("c[1] = %x \n", c[1]); 
    printf("i = %x \n", i); 

    return 0; 
} 

Output:

$ gcc 1.c 
$ ./a.out 
c[0] = 22 
c[1] = 11 
i = 1122 
$ 
+1

Bạn muốn chuyển num & 0xFF00 lên 8, phải không? (num & 0xFF00) >> 8. Nếu không, bạn chỉ có số nguyên 16 bit trong đó byte thấp xảy ra bằng không. Bạn vẫn không có byte. Cách khác, bạn chỉ có thể thay đổi: num >> 8; – abelenky

+0

@abelenky Bạn đúng .. bỏ qua điều đó! –

4

Nó thực sự phụ thuộc vào mục tiêu của bạn: tại sao bạn muốn chuyển đổi này đến một số unsigned char? Tùy thuộc vào câu trả lời cho rằng có một vài cách khác nhau để làm điều này:

  • Truncate: Đây là những gì đã được đề nghị.Nếu bạn chỉ đang cố gắng ép dữ liệu vào một hàm yêu cầu số unsigned char, chỉ cần bỏ uchar ch = (uchar)x (nhưng, tất nhiên, hãy cẩn thận về những gì xảy ra nếu int của bạn quá lớn).

  • Cụ thể endian: Sử dụng điều này khi đích của bạn yêu cầu định dạng cụ thể. Thông thường, mã mạng thích mọi thứ được chuyển đổi thành các chuỗi ký tự cuối cuối lớn:

    int n = sizeof x; 
    for(int y=0; n-->0; y++) 
        ch[y] = (x>>(n*8))&0xff; 
    

    sẽ làm điều đó.

  • Máy kết thúc. Sử dụng điều này khi không có yêu cầu cuối cùng và dữ liệu sẽ chỉ xuất hiện trên một máy. Thứ tự của mảng sẽ thay đổi trên các kiến ​​trúc khác nhau. Người ta thường chăm sóc này với union s:

    union {int x; char ch[sizeof (int)];} u; 
    u.x = 0xf00 
    //use u.ch 
    

    với memcpy:

    uchar ch[sizeof(int)]; 
    memcpy(&ch, &x, sizeof x); 
    

    hoặc qua các nhân đúc ngày càng nguy hiểm đơn giản (đó là hành vi không xác định, và đụng độ trên nhiều hệ thống):

    char *ch = (unsigned char *)&x;