Reputation: 2013
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
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
Reputation: 7542
There are two points:
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.You have to initialize the array array_uint
.
After this corrections I got 2000.0
for both versions.
Upvotes: 1