Liavba
Liavba

Reputation: 85

wrong conversion of two bytes array to short in c

I'm trying to convert 2 bytes array to an unsigned short.

this is the code for the conversion :

short bytesToShort(char* bytesArr)
{
    short result =(short)((bytesArr[1] << 8)|bytesArr[0]);
    return result;
}

I have an InputFile which stores bytes, and I read its bytes via loop (2 bytes each time) and store it in char N[] arr in this manner :

char N[3];
N[2]='\0';

while(fread(N,1,2,inputFile)==2)

when the (hex) value of N[0]=0 the computation is correct otherwise its wrong, for example :

0x62 (N[0]=0x0,N[1]=0x62) will return 98 (in short value), but 0x166 in hex (N[0]=0x6,N[1]=0x16) will return 5638 (in short value).

Upvotes: 0

Views: 87

Answers (2)

Ameen
Ameen

Reputation: 1857

The problem is sign extension due to using char. You should use unsigned char instead:

#include <stdio.h>

short bytesToShort(unsigned char* bytesArr)
{
    short result = (short)((bytesArr[1] << 8) | bytesArr[0]);
    return result;
}

int main()
{
    printf("%04x\n", bytesToShort("\x00\x11")); // expect 0x1100
    printf("%04x\n", bytesToShort("\x55\x11")); // expect 0x1155
    printf("%04x\n", bytesToShort("\xcc\xdd")); // expect 0xddcc

    return 0;
}

Note: the problem in the code is not the one presented by the OP. The problem is returning the wrong result upon the input "\xcc\xdd". It will produce 0xffcc where it should be 0xddcc

Upvotes: 1

John Bollinger
John Bollinger

Reputation: 181849

In the first place, it's generally best to use type unsigned char for the bytes of raw binary data, because that correctly expresses the semantics of what you're working with. Type char, although it can be, and too frequently is, used as a synonym for "byte", is better reserved for data that are actually character in nature.

In the event that you are furthermore performing arithmetic on byte values, you almost surely want unsigned char instead of char, because the signedness of char is implementation-defined. It does vary among implementations, and on many common implementations char is signed.

With that said, your main problem appears simple. You said

166 in hex (N[0]=6,N[1]=16) will return 5638 (in short value).

but 0x166 packed into a two-byte little-endian array would be (N[0]=0x66,N[1]=0x1). What you wrote would correspond to 0x1606, which indeed is the same as decimal 5638.

Upvotes: 3

Related Questions