Целочисленное значение изменяется при вставке в массив - PullRequest
0 голосов
/ 24 мая 2018

У меня странные проблемы с моим кодом, и я понятия не имею, что я делаю неправильно.Я относительно новичок в языке Си, поэтому я был бы очень признателен, если бы кто-то мог указать, что я делаю что-то глупое.

Я пытаюсь прочитать данные из файла в двумерный массивтип состояние .Тип состояния определяется следующим образом:

typedef uint8_t state [4][4];

Я определил метод read_block , который получает указатель файла в качестве параметра и возвращает указатель двухмерного типа состояние массив, который содержитпервые 16 байтов из этого файла.

state* read_block(FILE *fp) {
    state *arr = (state*) malloc(sizeof (state));
    uint8_t *temp = (uint8_t*) malloc(sizeof (uint8_t)*16);

    fread(temp, 16, 1, fp);

    /*
    for (int y = 0; y < 16; y++) {
        printf("%u ", temp[y]);
    }
    printf("\n");
    */

    int n = 0;
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            /*
            printf("%u ", temp[n]);
            */
            *arr[i][j] = temp[n];
            n++;
        }
    }

    return arr;
}

Код компилируется и работает нормально, но массив типа state , возвращаемый методом, всегда содержит одно неверное значение.В частности, значение в позиции [3] [0] всегда неверно.

Тестовый файл, который я пытаюсь прочитать, содержит числа:

0 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3

Я решил проверить, соответствуют ли значениячитаются правильно, и если я удаляю комментарии вокруг строк printf, я получаю в качестве вывода:

0 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3 
0 1 2 3 0 1 2 3 0 1 2 3 3 1 2 3

, в котором первая строка точно верна (это печатается сразу после fread () ),но по какой-то причине вторая строка неверна (это печатается при вставке значений в arr ).

Я не могу понять, что является причиной этого.Я также пытался читать значения по одному байту за раз с fread , но это же значение продолжает ошибаться.Я использую NetBeans, поэтому я не уверен, что это как-то вызвано этим.

Ответы [ 2 ]

0 голосов
/ 24 мая 2018

Не очень хорошая идея скрывать массив за typedef.В этом корень проблемы, поскольку arr на самом деле является указателем массива типа uint8_t (*)[4][4].И при разыменовании указателя массива вы должны сначала взять содержимое указателя, чтобы получить массив, а затем получить доступ к определенному индексу.То есть вам нужно будет сделать (*arr)[i][j] вместо *arr[i][j].

. Чтобы избежать этого подозрительного синтаксиса, вы можете использовать трюк и объявить указатель массива на самое внешнее измерение: uint8_t(*)[4].Тогда вы можете внезапно набрать arr[i][j].arr[i] тогда означает выполнение арифметики указателей для типа uint8_t(*)[4], а затем в полученном результате вы можете получить доступ к определенному индексу массива, [j].

В дополнение к проблеме приоритета оператора, вы, вероятно, захотитехранить данные непосредственно в массиве.Нет причины, по которой вы не можете сделать fread(arr, 16, 1, fp);, так как вы используете этот массив в том же порядке, в котором он выделен.

Я не проверял его, но вы должны иметь возможность заменить весьфункция с этим:

void read_block(FILE* fp, uint8_t (*arr)[4][4]) 
{
  const size_t size = sizeof(uint8_t[4][4]);
  *arr = malloc(size);
  fread(*arr, size, 1, fp);
}
0 голосов
/ 24 мая 2018

Вы работаете с приоритетом оператора.

*arr[i][j]

совпадает с

*(arr[i][j])   // or arr[i][j][0]

Это то же самое, только если i == 0, то есть в первой строке.

То, что вы хотите, это

(*arr)[i][j]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...