简体   繁体   中英

converting/combining two uint8_t to int16_t in Objective-C

Suppose I have a buffer filled with uint8_t, like what I would get by executing

uint8_t buffer[4];    
[inputStream read:buffer maxLength:4];

Again, suppose I know that this buffer now contains two signed 16-bit integers in big-endian format (even though the type of the buffer is uint8_t). How would I go about getting the results of each of the numbers?

I think that you have to use bitwise operators, and that you have to also convert from unsigned to signed, but I can't seem to figure it out completely.

A similar example with only uint8_t values would look something like this:

uint8_t buffer[2];
[inputStream read:buffer maxLength:2];
uint8_t value1 = buffer[0];
uint8_t value2 = buffer[1];

Any help would be most appreciated, as I'm sure this is a relatively simple question.

Update: To further clarify the problem: I know in advance that I'm receiving numbers from 0 to 255, even though they are 16-bit signed. So any negative numbers received are incorrect, and should probably be shifted up by 127, to account for the signed/unsigned difference.

to convert from big endian to little endian a signed short this function may be used

(from: convert big endian to little endian in C [without using provided func] )

int16_t swap_int16( int16_t val ) 
{
    return (val << 8) | ((val >> 8) & 0xFF);
}

So going back to your code

uint8_t buffer[4];    
[inputStream read:buffer maxLength:4];

You may try:

int16_t *value1;
int16_t *value2;

// set the pointers to the correct buffer location

value1 = (int16_t *)(&buffer[0]);
value2 = (int16_t *)(&buffer[2]);

// perform the conversion

*value1 = swap_int16( *value1 );
*value2 = swap_int16( *value2 );

// finally you may want to check the result

printf("Value1: %d\n", *value1 );
printf("Value2: %d\n", *value2 );

Note that this approach will swap the original bytes in buffer

The safest way is to use the following

#import <arpa/inet.h>
#import <stdint.h>
#import <string.h>


uint8_t* p = buffer;
uint16_t x0;
memcpy(&x0, p, sizeof(x0));
x0 =ntohs(x0);

uint16_t x1;
p += sizeof(uint16_t);
memcpy(&x1, p, sizeof(x1));
x1 = ntohs(x1);

This works even when the buffer's bytes are misaligned with respect to the uint16_t values (thus, using memcpy ).

Since it happens that network byte order equals "big endian", you can use ntohs which reads "swap short in network byte order to host byte order".

See also:

$man ntohs

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM