0

I am confused to convert byte array to short vice-versa and also int to byte array vice-versa in Objective-C.

I have seen in Java like following

  public static short byteArrayToShort(byte[] b) {
    if (b.length > 1) {
        return (ByteBuffer.wrap(b)).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().get();
    } else {
        return b[0];
    }
}

/**
 * Short to byte array.
 *
 * @param value the value
 * @return the byte[]
 */
public static byte[] shortToByteArray(short value) {
    return ByteBuffer.allocate(2).order(ByteOrder.LITTLE_ENDIAN).putShort(value).array();
}

/**
 * Int to byte array.
 *
 * @param value the value
 * @return the byte[]
 */
public static byte[] intToByteArray(int value) {
    return ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(value).array();
}

/**
 * Convert the byte array to an short starting from the given offset.
 * 
 * @param b The byte array
 * @return The integer
 */
public static int byteArrayToInt(byte[] b) {
    if (b.length > 1) {
        return (ByteBuffer.wrap(b)).order(ByteOrder.LITTLE_ENDIAN).asIntBuffer().get();
    } else {
        return b[0];
    }
}

In Objective-C I have tried like following:

//Byte to Short array
- (uint16_t*) byte2short:(uint8_t *)bytes size:(int)size{
    uint16_t*shorts = (uint16_t*)malloc(size/2);
    for (int i=0; i < size/2; i++){
       shorts[i] = (bytes[i*2+1] << 8) | bytes[i*2];
    }
    return shorts;
}
//Short to Byte array
- (uint8_t *) short2byte:(uint16_t*)shorts size:(int)size{

    uint8_t *bytes = (uint8_t *)malloc(size*2);
    for (int i = 0; i < size; i++)
    {
        bytes[i * 2] = (uint16_t) (shorts[i] & 0x00FF);
        bytes[(i * 2) + 1] = (uint16_t) (shorts[i] >> 8);
        shorts[i] = 0;
    }
    return bytes;
  }

I have tried like this and also I dont have idea in conversion of int to Byte array in Objective-c.

Please suggest me

1 Answers1

0

The problem with your code is that you are assuming that malloc somehow "knows" about the size of whatever is being allocated, in the same way that Java's array new knows the difference between allocating 5 ints and 5 shorts. Well, malloc does not. Unless you tell it otherwise, it allocates the required number of bytes. That's why when you do this

uint16_t*shorts = (uint16_t*)malloc(size/2);

and then write size/2 uint16_t into it, you overrun the buffer.

A proper way of allocating an array of primitives in C (and in Objective-C, which is a superset of C) is as follows:

size_t count = (size+1)/2; // Do not assume that size is even
uint16_t *shorts = malloc(sizeof(uint16_t)*count);

Now you have enough memory to fit all your shorts.

In your other function you should use

uint8_t *bytes = malloc(sizeof(uint8_t)*size*2);

Note that the cast is unnecessary in both cases. The type of bytes variable matters, though, because that's what determines the actual address written to in bytes[i * 2] and bytes[(i * 2)+1] expressions:

for (int i = 0; i < size; i++)
{
    bytes[i * 2] = (uint8_t) (shorts[i] & 0xFF);
    bytes[(i * 2) + 1] = (uint8_t) (shorts[i] >> 8);
    shorts[i] = 0;
}
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • Thanks alot for your answer. How can I convert int to Byte array and vice-versa. – iOS_Dev iOS Dec 17 '14 at 17:55
  • @iOS_DeviOS You can take the same approach as in your `unit16_t` code, but now that you have `uint32_t`, you need to process four bytes at a time instead of two bytes at a time. – Sergey Kalinichenko Dec 17 '14 at 18:02
  • @iOS_DeviOS No, that would be `bytes[i * 4] = (uint8_t) (ints[i] & 0xFF);` and `bytes[(i * 4)+1] = (uint8_t) ((ints[i] >> 8) & 0xFF);`, but you would also add `bytes[(i * 4)+2] = (uint8_t) ((ints[i] >> 16) & 0xFF);` and `bytes[(i * 4)+3] = (uint8_t) ((ints[i] >> 24) & 0xFF);`. I hope you see the pattern there - going for the next byte makes you shift an additional 8 bits to the right before masking the result with `0xFF`. – Sergey Kalinichenko Dec 17 '14 at 18:11
  • Excellent dasblinknlight. Thanks alot for your answer. And also in java, they are checking `LITTLE_ENDIAN`. How can I check in iOS? And also all ios devices are LITTLE_ENDIAN? – iOS_Dev iOS Dec 17 '14 at 18:15
  • @iOS_DeviOS I think that all iOS devices are little endian at the moment. However, this may change if Apple decides to go with a different processor architecture at some time in the future. It's best to use a little trick for checking endianness described [in this answer](http://stackoverflow.com/a/1001373/335858). – Sergey Kalinichenko Dec 17 '14 at 18:18
  • thanks alot for your help. I will try with all your suggestions and will gt back to you. Thanks alot once again. – iOS_Dev iOS Dec 17 '14 at 18:21