从按位操作数组接收错误值,包括C代码

时间:2012-03-03 20:39:08

标签: c arrays pointers bit-manipulation

我正在尝试更多地了解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

2 个答案:

答案 0 :(得分:1)

有两点:

  1. intArray中,你必须在循环结束条件之前递增指针(两次)

    p_a++; // here
    if (p_a == p_last)
        break;
    
    否则循环会经常迭代一次并覆盖未分配的内存。

  2. 您必须初始化数组array_uint

  3. 经过这些更正,我得到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版本的两个地方)