2012-09-02 59 views
10

Tôi có mảng char chưa ký [248]; chứa đầy byte. Giống như 2F AF FF 00 EB AB CD EF ..... Mảng này là Byte Stream của tôi mà tôi lưu trữ Dữ liệu của tôi từ UART (RS232) làm Bộ đệm.Chuyển đổi byte sang Int/uint trong C

Bây giờ tôi muốn chuyển đổi các byte trở lại thành uint16 và int32 của tôi.

Trong C# tôi đã sử dụng Lớp BitConverter để thực hiện việc này. ví dụ:

byte[] Array = { 0A, AB, CD, 25 }; 
int myint1 = BitConverter.ToInt32(bytes, 0); 
int myint2 = BitConverter.ToInt32(bytes, 4); 
int myint3 = BitConverter.ToInt32(bytes, 8); 
int myint4 = BitConverter.ToInt32(bytes, 12); 
//... 
enter code here 
Console.WriteLine("int: {0}", myint1); //output Data... 

Có chức năng tương tự trong C không? (Không .net, tôi sử dụng trình biên dịch Keil vì đang chạy trên một vi điều khiển)

Với mừng Sam

Giải pháp: Way A)

đầu tiên tôi đã phải chuyển đổi hoặc khởi tạo mảng như a uint8_t ARRAY [248]; Sau đó, tôi đã sử dụng mã này với sự giúp đỡ của bạn:

uint32_t* myint1 = (uint32_t *)&RXBUFF[2]; //test 
uint16_t* myint2 = (uint16_t *)&RXBUFF[6]; //test3 

Chú ý: Giá trị int "1985" trong hex được biểu diễn dưới dạng 0x07C1 trong myint2. Byte mà tôi đã mua là "C1 07" để Bộ vi điều khiển thay đổi Thứ tự Byte

Tôi cũng sẽ kiểm tra các Phương pháp khác.

WR Sam :)

Trả lời

8

Có. Giả sử byte của bạn đang ở:

uint8_t bytes[N] = { /* whatever */ }; 

Chúng tôi biết rằng, một số nguyên 16 bit chỉ là hai số nguyên 8 bit được ghép nối, tức làngười ta có một bội số của 256 hoặc cách khác được chuyển bởi 8:

uint16_t sixteen[N/2]; 

for (i = 0; i < N; i += 2) 
    sixteen[i/2] = bytes[i] | (uint16_t)bytes[i+1] << 8; 
      // assuming you have read your bytes little-endian 

Tương tự cho 32 bit:

uint32_t thirty_two[N/4]; 

for (i = 0; i < N; i += 4) 
    thirty_two[i/4] = bytes[i] | (uint32_t)bytes[i+1] << 8 
     | ((uint32_t)bytes[i+2] << 16 | (uint32_t)bytes[i+3] << 24; 
      // same assumption 

Nếu các byte được đọc lớn về cuối nhỏ, tất nhiên bạn đảo ngược thứ tự :

bytes[i+1] | (uint16_t)bytes[i] << 8 

bytes[i+3] | (uint32_t)bytes[i+2] << 8 
    | (uint32_t)bytes[i+1] << 16 | (uint32_t)bytes[i] << 24 

Lưu ý rằng có sự khác biệt giữa số cuối cùng trong số nguyên được lưu trữ và số cuối của kiến ​​trúc đang chạy. Câu trả lời cuối cùng được đề cập đến trong câu trả lời này là số nguyên được lưu trữ, tức là nội dung của bytes. Các giải pháp độc lập với phần cuối của kiến ​​trúc đang chạy kể từ endian-ness is taken care of when shifting.

+0

nếu kết thúc lớn của nó thì sao? – Sam

+0

sau đó bạn thay đổi các bit ít quan trọng nhất thay vì các bit quan trọng nhất. – devsnd

+0

@twall, tôi nghĩ bạn có nghĩa là byte. –

15

Không có chức năng tiêu chuẩn để làm điều đó cho bạn trong C. Bạn sẽ phải lắp ráp các byte trở lại vào số nguyên 16- và 32-bit của bạn mình. Hãy cẩn thận về endianness!

Dưới đây là một ví dụ đơn giản về cuối nhỏ:

extern uint8_t *bytes; 
uint32_t myInt1 = bytes[0] + (bytes[1] << 8) + (bytes[2] << 16) + (bytes[3] << 24); 

Đối với một hệ thống lớn về cuối nhỏ, nó chỉ là thứ tự ngược lại:

uint32_t myInt1 = (bytes[0] << 24) + (bytes[1] << 16) + (bytes[2] << 8) + bytes[3]; 

Bạn có thể có thể nhận được ngay với:

uint32_t myInt1 = *(uint32_t *)bytes; 

Nếu bạn cẩn thận về các sự cố liên kết.

+1

Tôi sẽ truyền mỗi 'byte []' thành 'uint32_t' trước khi dịch chuyển. Như đã viết ở trên, chúng sẽ được đưa vào 'int' trước khi thực hiện các thay đổi, nhưng 'int' không cần phải là 32 bit. –

+0

Điều đó sẽ an toàn nhất, được đồng ý. –

+0

Giả sử 'byte' là bản địa cuối cùng, bạn sẽ gặp phải những vấn đề liên kết nào? Hoặc, tôi đoán, loại tình huống nào làm cho căn chỉnh trở thành một vấn đề? – Azmisov

6

Bạn có thể tạo trực tiếp con trỏ uint16_t * từ mảng của mình.

uint8_t bytes[N] = { /* whatever */ }; //Shamelessly stolen from Shanbaz 

uint16_t* viewAsUint16_t = (uint16_t *)&bytes[0]; 

Bây giờ bạn có thể sử dụng con trỏ để truy cập các phần tử.

Lưu ý rằng điều này giả định độ bền là chính xác cho máy của bạn. Bạn có thể cần phải lặp qua các số này uint16_t và sử dụng các chức năng như ntohs (phải khả dụng trên hầu hết các hệ điều hành) để khắc phục sự cố.

+0

tôi sẽ thử ngay bây giờ. – Sam

+0

Tôi đã thử mã của bạn nhưng có vẻ như nó không hoạt động. Tôi đã lưu đầu ra từ trình gỡ lỗi và bảng điều khiển dưới dạng hình ảnh: [link] (http://s18.postimage.org/fipv7svp3/debugbyte.png) – Sam

0
  char letter = 'A'; 
      size_t filter = letter; 
      filter = (filter << 8 | filter); 
      filter = (filter << 16 | filter); 
      filter = (filter << 32 | filter); 
      printf("filter: %#I64x \n", filter); 

kết quả: "lọc: 0x4141414141414141"

0

Trong trường hợp ít về cuối nhỏ, có thể bạn không chỉ cần sử dụng memcpy?

memcpy((char*)&myint1, aesData.inputData[startindex], length);