Реверсивный массив void и тип данных для приведения - PullRequest
0 голосов
/ 04 ноября 2018

Я выделил память для массива следующим образом:

void *buf;
buf = calloc(8192, 1);

Теперь я прочитал 8192 байта в массив из потока файлов необработанного файла:

uint32_t fpos = 0;
int n;
n = fread(buf,1,8192,file);
fpos += n;

Я бы использовал такую ​​функцию, как:

static void reverseBuffer(void *buf){
        for(int a = 0; a < sizeof(buf)>>1; a++){
            uint8_t temp = (uint8_t) buf[a];
            buf[a] = buf[sizeof(buf) - a - 1];
            buf[sizeof(buf) - a - 1] = temp;
        }
} 

Очевидно, что это на самом деле не работает, как мне нужно привести массив и какой тип данных мне нужно использовать? Я попытался привести его к uint_8, поскольку он гарантированно имеет размер 1 байт.

ура

Ответы [ 3 ]

0 голосов
/ 04 ноября 2018

Невозможно инвертировать массив, не зная типов.

Рассмотрим, что значит обратить массив. Мы хотим поменять местами первый и последний элемент, второй и второй на последний элемент и т. Д.

[0, 1, 2, 3] => [3, 2, 1, 0]

Это работает, потому что мы знаем размер каждого элемента. На самом деле данные существуют как единицы и нули.

Мы можем поменять местами первый и последний элемент, только если знаем, насколько велик первый и последний элемент.

// Element size is 3 bits
[000, 001, 010, 100] => [100, 010, 001, 000]

Не зная размера каждого элемента, невозможно узнать, где останавливается первый элемент и что следует поменять местами.

// Unknown element size
000001010100

// Element size 1
[0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0] => [0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0]

// Element size 2
[00, 00, 01, 01, 01, 00] => [00, 01, 01, 01, 00, 00]

// Element size 4
[0000, 0101, 0100] => [0100, 0101, 0000]

Типы определяют, сколько битов образуют один элемент (например, int может быть 32-битным, а long - 64-битным).

Не зная типа, невозможно узнать размер элемента и не зная размера элемента, невозможно перевернуть список.

0 голосов
/ 04 ноября 2018

как мне нужно привести массив и какой тип данных мне нужно использовать? Я попытался привести его к uint_8, поскольку он гарантированно имеет размер 1 байт.

Итак, вы почти у цели.

Просто вы не можете разыменовать указатель void, так как не ясно, к какому типу это следует оценивать, так как он указывает на void.

Решение состоит в том, чтобы привести указатель к некоторому специфическому типу указателя. В вашем случае uint8_t* и только потом разыменовывайте его.

Также ваш код предполагает, что sizeof buf даст вам размер массива, чего он не имеет. Он дает вам размер buf и, поскольку buf является указателем (void*), вы получаете размер указателя, который составляет 4 или 8 байт, в зависимости от операционной системы, в которой вы запускаете этот код.

Итак, вам нужно , чтобы функция знала о размере массива. Это можно сделать, просто передав его.

Функция может выглядеть следующим образом:

static void reverseBuffer(size_t size, void * buf) {
    for (size_t a = 0; a < size >> 1; a++) {
        uint8_t temp = ((uint8_t*) buf)[a];
        ((uint8_t*) buf)[a] = ((uint8_t*) buf)[size - a - 1];
        ((uint8_t*) buf)[sizeof- a - 1] = temp;
    }
} 

или введите локально правильно набранную переменную:

static void reverseBuffer(size_t size, void * buf) {
    uint8_t * p = buf;

    for (size_t a = 0; a < size >> 1; a++) {
        uint8_t temp = p[a];
        p[a] = p[size - a - 1];
        p[size - a - 1] = temp;
    }
} 

или уже определите функцию, используя правильный тип:

static void reverseBuffer(size_t size, uint8_t * p) {
    for (size_t a = 0; a < size >> 1; a++) {
        uint8_t temp = p[a];
        p[a] = p[size - a - 1];
        p[size - a - 1] = temp;
    }
} 

Назовите это так

  reverseBuffer(8192, buf);
0 голосов
/ 04 ноября 2018

В вашем цикле, возможно, sizeof(buf)>>1 вместо sizeof(buf)>>2 сделает ваш код работоспособным.

...