2014-02-20 4 views
2

Я пробовал свою руку на C, применяя игру Жизни Конвея.Как использовать двойной указатель для матрицы (двумерный массив)?

Я пытаюсь динамически строить две сетки (int), один для текущего и один для следующего поколения, поэтому после того, как я определяю, как выглядит следующее поколение, я просто переключаю указатели.

Сначала я попытался безнадежно определить указатель на сетку, как int * grid, который вы не можете индексировать со вторым набором скобок, например [][], потому что - очевидно - первый набор скобок возвращает int.

Я также пробовал что-то вроде int * grid[HEIGHT][WIDTH], но это создает проблемы с назначением одного указателя, подобного этому другому. (И на самом деле, я понятия не имею, что это на самом деле делает в памяти!)

В моей наивной надежде, я думал, что следующее может работать после спотыкания по двойным указателям. Программа компилируется, но не работает при запуске в указанной строке. (В Windows я не получаю больше подробностей, кроме того, что имя проблемного события: APPCRASH).

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: Это не настоящая программа, а просто доказательство концепции проблемы.

#include <stdio.h> 
#include <stdlib.h> 

int HEIGHT = 20; 
int WIDTH = 20; 

int ** curr_gen; // Current generation 
int ** next_gen; // Next generation 

/* Entry Point main */ 
int main(int argc, char** argv) { 

    // Allocate memory for the grids 
    curr_gen = malloc(sizeof (int) * WIDTH * HEIGHT); 
    next_gen = malloc(sizeof (int) * WIDTH * HEIGHT); 

    curr_gen[0][0] = 0; //<< PROGRAM FAILS HERE 

    // Release heap resources 
    free(curr_gen); 
    free(next_gen); 

    return 0; 
} 
+0

http://c-faq.com/ aryptr/dynmuldimary.html –

+0

У вас не может быть ответа на одну ссылку.Чтобы обработать ваш случай, вам нужно понять, что происходит в памяти. – ThunderGr

ответ

0

Обычным способом это сделать, описано в http://c-faq.com/aryptr/dynmuldimary.html

+0

Мне нравится это решение, хотя при доступе к моей сетке с помощью [0] [0] Я все еще получаю ошибку сегментации, но я отправлю это как отдельный вопрос. – mydoghasworms

+0

Ничего, мне удалось решить проблему, поэтому я приму этот ответ. Большое спасибо. – mydoghasworms

+1

Обратите внимание: части ответа здесь, на этом сайте или удалены ваши риски для публикации. [См. часто задаваемые вопросы, в которых упоминаются ответы, которые «едва ли больше, чем ссылка».] (http://stackoverflow.com/faq#deletion). Вы можете по-прежнему включайте ссылку, если хотите, но на в качестве «ссылки». Ответ должен стоять сам по себе, не нуждаясь в ссылке. – Taryn

2

Вы можете просто выделить пространство и наложить указатель на тип, определяющий размеры столбцов и строк. Поиск указателя через [] [] стоит дорого. И построение динамического многомерного массива таким образом должно быть зарезервировано для массивов ragid. IE: используйте его только при необходимости.

Вы можете определить тип:

typedef int MyArray[20][20]; 

А затем отливали указатель таНоса к типу вы хотите:

MyArray * curr_gen = (MyArray *) malloc(...); 

Однако это предполагает, что у вас есть постоянный, известный во время компиляции высоты времени и ширины. Если он должен быть динамическим, то обязательно используйте индекс в методе таблицы указателей. Но имейте в виду, что фактический указатель поднял голову, должен быть загружен в последнюю возможную минуту, ведущую к киоскам трубопровода, и потенциальные промахи в кэше. Сделать это в 100 раз дороже, чем просто выполнять математику через [row * 20 + col].

Итак, реальный вопрос, который вы должны задать себе: «Нужно ли работать быстро, или я хочу, чтобы код выглядел« Аккуратно »?

+0

Выведенный typedef не компилируется для меня, говоря «ошибка: ожидаемый идентификатор или» («до» ['токен ". – mydoghasworms

+0

Извините слишком много C#. это вместо: typedef int MyArray [20] [20]; – Dan

+0

Или для указателя на указанный массив: typedef int (* MyArray) [20] [20]; – Dan

0

Вы можете просто использовать int* как тип сетки в моем пути.

Преобразовать положение 2D-1D с помощью макроса определить или функцию:

#define MATRIX2INDEX(x, y, width) ((x) + (y) * (width)) // `width` is the max of x + 1 :) 
int Matrix2Index(int x, int y, int width) 
{ 
    return MATRIX2INDEX(x, y, width); 
} 

Посетите данные по 2D позиции в int*:

int* grid = (int*)malloc(sizeof(int) * WIDTH * HEIGHT); 
grid[MATRIX2INDEX(0, 0, WIDTH)] = 0; // here: get the data you want by 2D position 
free(grid); grid = NULL; 
+1

Thats опасный макрос .. Рассмотрим, что происходит, когда вы передаете что-то вроде «row + rowOffset» для значения Y. Смещение строки умножается на ширину. И твой сломан. Каждый раз, когда вы пишете такой макрос, вам нужно явно принудительно выполнить порядок операций: #define MATRIX2INDEX (x, y, width) ((x) + (y) * (ширина)) – Dan

+0

Вы правы. Благодарю. Я пересмотрел его и буду более осторожным. –

Смежные вопросы