kwroot
kwroot

Reputation: 77

Converting unsigned char array to signed short in C

I want to convert an array of unsigned char to a signed int! I've already done some try, and the conversion works for the single element like this:

  unsigned char byte[2];
  signed char *valueS[2];
  byte[0] = 0b11110111;
  byte[1] = 0b00001001;

  //Conversion
  for(int i = 0; i < 2; i++)
  {
     valueS[i] = (signed char*)&byte[i];
  }

  //Result
  printf("Val 0 -> %d \n", *valueS[0]); // print -9 Correctly
  printf("Val 1 -> %d \n", *valueS[1]); // print 9 Correctly

  //But when i try to print a 16 bit signed
  printf("Int %d \n", *(signed short*)valueS); //It doesn't work! I expected -2295

How can i get the 16 bit signed int from that unsigned char array? Thank you in advance!

Upvotes: 1

Views: 1153

Answers (1)

John Bollinger
John Bollinger

Reputation: 181519

How can i get the 16 bit signed int from that unsigned char array?

Supposing you mean you want to obtain the int16_t whose representation is byte-for-byte identical to the contents of an arbitrary array of two unsigned char, the only conforming approach is to declare an int16_t object and copy the array elements to its representation. You could use the memcpy() function to do the copying, or you could do it manually.

For example,

#include <stdint.h>

// ...

    unsigned char byte[2] = { 0xF7, 0x05 };
    int16_t my_int;
    unsigned char *ip = (unsigned char *) &my_int;

    ip[0] = byte[0];
    ip[1] = byte[1];
    printf("Int %d \n", my_int);

You might see a recommendation to use a pointer aliasing trick to try to reinterpret the bytes of the array directly as the representation of an integer. That would take a form similar to your code example, but such an approach is non-conforming, and formally it yields undefined behavior. You may access the representation of an object of any type via a pointer to [unsigned] char, as the code in this answer does, but, generally, you may not otherwise access an object via a pointer to a type incompatible with that object's.

Note also that the printf above is a bit sloppy. In the event that int16_t is a different type from int, such as short int, the corresponding printf directive for it will have a length modifier in it -- likely %hd. But because of details of the way printf is declared, it is the result of promoting my_int to int that will be passed to printf. That rescues the mismatch, and in practice, the printed result will be the same as if you used the correct directive.

Upvotes: 2

Related Questions