2011-01-24 76 views
6

Tôi có mảng char chưa ký với 2 phần tử đại diện cho một số nguyên đã ký. Làm thế nào tôi có thể chuyển đổi 2 byte này thành một số nguyên đã ký?Chuyển đổi ký tự chưa ký thành số nguyên đã ký

Sửa: Các mảng char unsigned là trong little endian

+0

Bạn phải xem ra cho endian , xem http://en.wikipedia.org/wiki/Endianness –

+0

Có một số cách trong đó hai 'unsigned char' có thể đại diện cho một số nguyên đã ký. Bạn nên cụ thể hơn về điều đó. –

Trả lời

6

Để an toàn tối đa, sử dụng

int i = *(signed char *)(&c[0]); 
i *= 1 << CHAR_BIT; 
i |= c[1]; 

cho về cuối lớn. Hoán đổi c[0]c[1] cho ít người dùng cuối.

(Giải thích: chúng tôi giải thích các byte tại c[0] như một signed char, sau đó thay đổi số học trái nó một cách cầm tay, sau đó thêm vào c[1].)

+0

Như tôi đã nói sau, nếu bạn chỉ cần cast char unsigned để ký char bạn có nguy cơ bit dấu được mở rộng. Tốt hơn nên che giấu kết quả bằng 0x0000FFFF để đảm bảo bit dấu hiệu thấp. –

+0

@ Mr.Gate, tôi không phải là "chỉ" đúc 'unsigned char' thành' char char'. Tôi đang sử dụng một con trỏ đúc để diễn giải lại các mẫu bit như 'ký char', sau đó thúc đẩy để' int'. –

+1

Hầu hết các trình biên dịch ** không bỏ qua ** quy tắc bí danh. GCC gần như chắc chắn sẽ tạo ra mã mà không làm những gì bạn muốn trừ khi bạn vượt qua nó tùy chọn đặc biệt. –

2

Nó phụ thuộc endian. Something cho về cuối lớn:

unsigned char x[2]; 
short y = (x[0] << 8) | x[1] 

Something cho little endian:

unsigned char x[2]; 
short y = (x[1] << 8) | x[0] 
+1

* unsigned * chars ... –

+0

Điều này không có khả năng hoạt động trên nhiều hệ thống, đặc biệt khi đồng bằng 'char' được ký (' x [0] 'và' x [1] 'sẽ được mở rộng, vì vậy nếu ít quan trọng nhất là số âm, byte trên sẽ được đặt thành tất cả 1 theo bitwise OR). – caf

5

bọc chúng trong một liên minh:

union { 
    unsigned char a[2]; 
    int16_t smt; 
} number; 

Bây giờ sau khi điền mảng, bạn có thể sử dụng như number.smt

+2

@VGE: chuyển đổi 'short' thành' int' được xác định rõ. Mặc dù tôi khuyên bạn nên sử dụng 'int16_t' thay vì' short'. –

1

Giải pháp di động:

unsigned char c[2]; 
long tmp; 
int result; 

tmp = (long)c[0] << 8 | c[1]; 
if (tmp < 32768) 
    result = tmp; 
else 
    result = tmp - 65536; 

Giả định rằng các byte trong mảng đại diện cho 16 bit, bổ sung hai, số nguyên được ký cuối lớn. Nếu chúng là một số nguyên cuối nhỏ, chỉ cần hoán đổi c[1]c[0].

(Trong trường hợp chắc chắn rằng đó là những bổ sung, sử dụng 65535 thay vì 65536 như giá trị trừ Đăng độ richter là trái như một bài tập cho người đọc;).

+0

Tôi muốn che dấu kết quả bằng 0x0000FFFF.Điều này đảm bảo rằng, ngay cả khi bit dấu mở rộng, bạn sẽ cấp cho valute nằm trong phạm vi 0x0000FFFF và 0. –

+0

@ Mr.Gate: Không cần phải che mặt nạ. Vì 'c [0]' và 'c [1]' là số dương giữa 0 và 255, 'tmp' là số dương trong khoảng 0 đến 65535. Số âm duy nhất được tạo ra trong phép trừ cuối cùng - không có cơ hội của tiện ích mở rộng dấu không mong muốn. – caf

Các vấn đề liên quan