Sassa
Sassa

Reputation: 2013

Receiving wrong value from bitwise manipulated array, C code included

I'm trying to learn more about bitwise and see how i can improve the performance of my code with it, so, I've made an test code, in that code I make 2 arrays, one with unsigned chars and another with unsigned integers, the idea is to simulate an rgba array, and see the differences in manipulating it with just pointer or with bitwise.

To be sure that everything is working, in the end I do an sum of all values of the array, the problem is that the values from the array manipulated with pointer differs from the one with bitwise, for now, the array have just 4 positions in the integer array and 16 in the char one. they should give me the same results in the end, but only the char one give me it (2000 is the corrent result).

Here is the code:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

inline double
ucharArray(void);

inline double
intArray(void);

int32_t
main(int32_t argc, int8_t* argv[])
{
  double sum = 0;

  sum = ucharArray();

  printf("%lf\n", sum);

  sum = 0;

  sum = intArray();

  printf("%lf\n", sum);

  return 0;
}

inline double
intArray(void)
{
  double sum = 0;
  uint32_t* array_uint = (uint32_t*) malloc(2 * 2 * sizeof(uint32_t));

  register uint32_t* p_a = array_uint;
  register uint32_t* p_last = p_a + 2 * 2;

  for (;;)
  {
    *p_a |= (50 << 24);
    *p_a |= (100 << 16);
    *p_a |= (150 << 8);
    *p_a |= 200;

    if (p_a == p_last)
      break;
    p_a++;
  }

  p_a = array_uint;
  for (;;)
  {
    sum += (*p_a & 0xFF000000) >> 24;
    sum += (*p_a & 0x00FF0000) >> 16;
    sum += (*p_a & 0x0000FF00) >> 8;
    sum += *p_a & 0x000000FF;

    if (p_a == p_last)
      break;
    p_a++;
  }

  free(array_uint);

  return sum;
}

inline double
ucharArray(void)
{
  double sum = 0;
  uint8_t* array_uchar = (uint8_t*) malloc(2 * 2 * 4 * sizeof(uint8_t));

  register uint8_t* p_a = array_uchar;
  register uint8_t* p_last = p_a + 2 * 2 * 4;

  for (;;)
  {
    *p_a = 50;
    p_a++;
    *p_a = 100;
    p_a++;
    *p_a = 150;
    p_a++;
    *p_a = 200;
    p_a++;

    if (p_a == p_last)
      break;
  }

  p_a = array_uchar;
  for (;;)
  {
    sum += *p_a;
    p_a++;
    sum += *p_a;
    p_a++;
    sum += *p_a;
    p_a++;
    sum += *p_a;
    p_a++;

    if (p_a == p_last)
      break;
  }

  free(array_uchar);

  return sum;
}

And heres is my output:

~ $ gcc test.c -g
~ $ ./a.out 
2000.000000
3484.000000

Upvotes: 0

Views: 246

Answers (2)

Dmitri
Dmitri

Reputation: 9375

One issue is that you're bitwise ORing values into the bytes of your int, but you haven't zeroed it first -- this means you're getting the ORed combination of the values you're deliberately including, and whatever was (randomly) already there. So change this:

*p_a |= (50 << 24);
*p_a |= (100 << 16);
*p_a |= (150 << 8);
*p_a |= 200;

...to this:

*p_a = (50 << 24) | (100 << 16) | (150 << 8) | 200;

...or just set *p_a to zero first.

However, your code also assumes a big-endian system. If you're on a little-endian system like x86, you also need to reverse the positions of the values:

*p_a = 50 | (100 << 8) | (150 << 16) | (200 << 24);

...in order to match what you do with the ucharArray() version.


@Christian Ammer is also right that:

if (p_a == p_last)
  break;
p_a++;

...needs to be:

p_a++;
if (p_a == p_last)
  break;

...so that the test comes after the increment. (in two places in your int version)

Upvotes: 1

Christian Ammer
Christian Ammer

Reputation: 7542

There are two points:

  1. In intArray you have to increment the pointer before the loop-end condition (two times)

    p_a++; // here
    if (p_a == p_last)
        break;
    
    Otherwise the loop iterates once to often and you overwrite unallocated memory.

  2. You have to initialize the array array_uint.

After this corrections I got 2000.0 for both versions.

Upvotes: 1

Related Questions