我正在尝试更多地了解bitwise,看看我如何用它来提高代码的性能,所以,我已经制作了一个测试代码,在那段代码中我制作了2个数组,一个是无符号字符,另一个是使用无符号整数,我们的想法是模拟一个rgba数组,并看到用指针或按位操作它的差异。
为了确保一切正常,最后我对数组的所有值求和,问题是用指针操作的数组中的值与按位的数组不同,目前,数组有整数数组中只有4个位置,char中只有16个位置。他们最终应该给我相同的结果,但只有char给我一个(2000年是正确的结果)。
以下是代码:
#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;
}
继承人是我的输出:
~ $ gcc test.c -g
~ $ ./a.out
2000.000000
3484.000000
答案 0 :(得分:1)
有两点:
在intArray
中,你必须在循环结束条件之前递增指针(两次)
p_a++; // here
if (p_a == p_last)
break;
否则循环会经常迭代一次并覆盖未分配的内存。
您必须初始化数组array_uint
。
经过这些更正,我得到2000.0
这两个版本。
答案 1 :(得分:1)
一个问题是你将值按位OR运算到int的字节中,但是你没有先将它归零 - 这意味着你得到了你故意包含的值的ORed组合,等等是(随机)已经在那里。所以改变这个:
*p_a |= (50 << 24);
*p_a |= (100 << 16);
*p_a |= (150 << 8);
*p_a |= 200;
......对此:
*p_a = (50 << 24) | (100 << 16) | (150 << 8) | 200;
...或者先将*p_a
设为零。
但是,您的代码也假定为big-endian系统。如果你使用像x86这样的小端系统,你还需要反转值的位置:
*p_a = 50 | (100 << 8) | (150 << 16) | (200 << 24);
...以便与您使用ucharArray()
版本进行匹配。
@Christian Ammer也是对的:
if (p_a == p_last)
break;
p_a++;
......需要:
p_a++;
if (p_a == p_last)
break;
...以便在增量之后进行测试。 (在你的int版本的两个地方)