1

I'm trying to extract some color codes from an image buffer. When I read out a memory adres from the buffer it returns an int value that contains the color codes of two pixels. My goal is to get each color code as an separate int value.

For example when I read out a memory adres from the image buffer it returns the decimal value: 142149753.

Because this decimal value it's 9 characters long I can't simply spit it into two int values. So I tried to convert the value to a hexadecimal with the printf function which gave me the value: 08790879‬.

Now I can see de two 16-bit color codes I need: 0879 and 0879.

int firstColorCode;
int secondColorCode;

int colorcodes = IORD_ALTERA_AVALON_PIO_DATA(0x08000000 + 123204);

printf("%08x\n", colorcodes);

How can I get the two color codes into the corresponding int variables in code?

Disclaimer: I'm new to C and it feels like I'm asking a stupid question :/

kiran Biradar
  • 12,700
  • 3
  • 19
  • 44
Hampel
  • 13
  • 2

3 Answers3

2

You need to use right shift to get the first color code. For the second color code, you need to either mask or typecast with uint16_t

firstColorCode = (uint16_t) (colorcodes >> 16u);
secondColorCode = (uint16_t) colorcodes;

You can also use,

firstColorCode = (colorcodes >> 16u) & 0xFFFFu;
secondColorCode = colorcodes & 0xFFFFu;

You should use unsigned int values for the colorcodes to avoid undefined behavior in the right shifts.

uint16_t firstColorCode;
uint16_t secondColorCode;
uint32_t colorcodes; 

Also, as suggested by @lundin i have added u to the constants to make them unsigned constants.

Rishikesh Raje
  • 8,556
  • 2
  • 16
  • 31
  • There shouldn't be any signed types anywhere in your code. This is unstable and bug-prone, the code is shifting an `int` type which potentially has the sign bit set, but we don't want any signs. You must cast `colorcodes` to `unsigned int` before shifting. Also make a habit of using `u` suffix on all hex literals. – Lundin Jul 02 '19 at 11:36
0

There's some basic rules when walking the C type system mine field:

  • Never use signed types when doing any form of bitwise manipulations.
  • Never use signed types when you don't actually want negative numbers.
  • Be careful when using small integer types such as char, short, uint16_t etc because they get implicitly promoted to signed int when used in expression.
    More info about implicit promotions: Implicit type promotion rules
  • Be wary of hex literals because they have various subtle rules regarding which type they get. Always suffix them with u to prevent them from being a signed type.
  • Never write leading zeroes in C code. If you write something like 0879 in C, it means octal format.

By taking more care of types, we can split your 32 bit number in two like this:

#include <stdint.h>

uint16_t first;
uint16_t second;

uint32_t colorcodes = IORD_ALTERA_AVALON_PIO_DATA(0x8000000u + 123204u);

first = (uint16_t) (colorcodes >> 16);
second = (uint16_t) colorcodes;

Print uint16_t as hex by using printf("%"PRIx16, first), from inttypes.h.

Lundin
  • 195,001
  • 40
  • 254
  • 396
0

Just divide the number by 65536. The remainder will be the lower part of your half, and the quotient the most significative part.

BTW, the idea of some comments on working with unsigned values is good also, and consider that right shifting an unsigned int number by 16 is the equivalent to divide by 2^16 == 65536.

Luis Colorado
  • 10,974
  • 1
  • 16
  • 31