Получение неверного значения из побитового массива, включая код C - PullRequest
0 голосов
/ 04 марта 2012

Я пытаюсь больше узнать о побитовом коде и посмотреть, как я могу улучшить производительность своего кода с его помощью, поэтому я сделал тестовый код, в этом коде я делаю 2 массива, один с неподписанными символами, а другой с целыми числами без знака идея состоит в том, чтобы смоделировать массив rgba и увидеть различия в манипулировании им с помощью только указателя или побитового преобразования.

Чтобы быть уверенным, что все работает, в конце я делаю сумму всех значений массива, проблема в том, что значения из массива, управляемого с помощью указателя, отличаются от значений с побитовым, на данный момент массив имеет всего 4 позиции в целочисленном массиве и 16 в символьной. в итоге они должны дать мне те же результаты, но только один символ даст мне (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 ]

1 голос
/ 04 марта 2012

Одна из проблем заключается в том, что вы поразрядно присваиваете значения 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 на ноль вначале.

Однако вашКод также предполагает систему с прямым порядком байтов.Если вы используете систему с прямым порядком байтов, такую ​​как x86, вам также необходимо поменять местами значения:

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

..., чтобы соответствовать тому, что вы делаете с версией ucharArray().


@ Кристиан Аммер также прав, что:

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

... должно быть:

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

... так, чтобы тест проходилпосле приращения.(в двух местах в вашей версии int)

1 голос
/ 04 марта 2012

Есть две точки:

  1. В intArray необходимо увеличить указатель до условия окончания цикла (два раза)

    p_a++; // here
    if (p_a == p_last)
        break;
    
    В противном случае цикл повторяется один раз в частотуи вы перезаписываете нераспределенную память.
  2. Вы должны инициализировать массив array_uint.

После этих исправлений я получил 2000.0 для обоихверсии.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...