Изменение 2D-массива в функции с использованием арифметики с указателями - PullRequest
0 голосов
/ 13 октября 2018

У меня возникли проблемы с функцией, которую я написал для инициализации 2D-сетки для реализации игры жизни Конвея.Эта функция initialize (bool *, int, int) использует арифметику указателей для доступа ко всем значениям в массиве 2d, указатель которого я передаю.

main.cpp

#include "logic.cpp"
#include <SFML/Graphics.hpp>

using namespace std;

const unsigned int WIDTH = 640;
const unsigned int HEIGHT = 640;
const int RESOLUTION = 10;

const int rows = (WIDTH/RESOLUTION) - 1;
const int cols = (HEIGHT/RESOLUTION) - 1;

int main()
{
    bool curr_gen[rows][cols];
    bool next_gen[rows][cols];

    bool* curr = &curr_gen[0][0];
    bool* next = &next_gen[0][0];

    initialize(curr, rows, cols);

    /*sf::RenderWindow window(sf::VideoMode(WIDTH, HEIGHT), "Conway's Game of Life");
    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();
        }
        window.clear();
        window.display();
    }*/
    return 0;
}

logic.cpp

#include <iostream>
#include <ctime>

void initialize(bool* p, int r, int c)
{
    srand(time(NULL));
    for(int i=0; i<r; i++)
    {
        for(int j=0; j<c; j++)
        {
             if(rand()% 2)
                *(*(p+i)+j) = true;
             else
                *(*(p+i)+j) = false;
        }
    }
}

Все ошибки, которые я получаю, скажем недопустимый аргумент типа унарного '*' (есть 'int') .На мой взгляд, (* (p + i) + j) дает адрес элемента массива 2d (& arr [i] [j]), а при разыменовании я могу получить доступ к arr [i] [j] иИзмени это.Я был бы очень признателен, если бы кто-то мог указать на ошибку в моих рассуждениях.Я использую компилятор GNU GCC в Code :: Blocks.

Ответы [ 2 ]

0 голосов
/ 13 октября 2018

Давайте посмотрим на логику вашего кода:

*(*(p+i)+j) = true;

Эта попытка эквивалентна p[i][j], а фактически равна .Проблема в том, что p не является bool[][].Это даже не bool**.Это bool*, который является указателем на bool, который может также быть первым элементом массива.

Обратите внимание, что то, что я собираюсь объяснить, действительно только для T[][] массивов.Это недопустимо для динамически размещаемого массива, у которого есть строки, также динамически выделяемые.

То, что я собираюсь объяснить, основано на том факте, что двумерный (или три, или четыре ...) массив измерений реализован какодин, большой, одномерный массив.Если у вас есть bool[3][3], это на самом деле bool[9] под капотом, с некоторыми преимуществами в отношении синтаксиса доступа (в виде [x][y] доступа).

Теперь давайте еще раз посмотрим на ваш код:

for(int i=0; i<r; i++)
{
    for(int j=0; j<c; j++)
    {
         if(rand()% 2)
            *(*(p+c)+j) = true;
         else
            *(*(p+c)+j) = false;
    }
}

Ваш внешний цикл for() перебирает строки массива.Ваш внутренний цикл for() перебирает элементы одной строки.

Если вы передали bool** как p, на самом деле будет работать !Но ты не сделал.Вы передали bool*, который указывает на один массив.Вы используете преимущества реализации T[][] (двумерный массив) в форме работы с ним, как если бы он был больше T[].

Теперь вам нужен доступ к i-й строкеи j й элемент.Для этого вам необходимо:

  • удалить двойную разыменование.Вы работаете с одномерным массивом

  • исправьте свою логику относительно позиции заинтересованного элемента

Простое исправление могло бы изменить это:

*(*(p+i)+j) = true;

на это:

*(p+i*c+j) = true;

Второй разыменяет элемент, который находится в i-й строке (вы должны умножить i на c, потому чтонапример, первый элемент третьей строки является 3*c -ым элементом вашего одномерного представления вашего двумерного массива) и находится в позиции j.

0 голосов
/ 13 октября 2018

Вы не можете разыменовать указатель дважды.У вас есть только bool*, а не bool**.

Использование *(p+i*c+j).

...