Я изучаю C и пробую новые вещи, чтобы проверить, на что я способен. Я написал код, который создает множество Мандельброта с заданным разрешением (RES), которое находится #define RES
в файле .h. Это работает и дает хороший результат для разрешений менее 321. По какой-то причине, когда RES > 321
, код больше не выполняется.
Я использую GCC и строю вывод с помощью Gnuplot. Я пытался выполнить отладку с помощью отладчика, но RES > 321
функция main
больше не запускается? Я добавил печать в первую строку main()
, чтобы увидеть, и это не запускается. Создан исполняемый файл и программа компилируется без ошибок?
#include <stdio.h>
#include <math.h>
#define MAX_DEPTH 100
#define RES 321
typedef struct complex_t {
double re;
double im;
} complex;
void init_complex_grid(complex complex_grid[RES][RES], double left, double right, double top, double bottom);
int converge(complex a);
complex add_complex(complex a, complex b);
complex square_complex(complex a);
double mag_complex(complex a);
void output_grid(unsigned int grid[RES][RES]);
int main(void) {
// printf("HERE\n");
int i, j;
unsigned int convergence_grid[RES][RES];
complex complex_grid[RES][RES];
init_complex_grid(complex_grid, -2.5, 1, 1, -1);
for (i = 0; i < RES; i++) {
for (j = 0; j < RES; j++) {
convergence_grid[i][j] = converge(complex_grid[i][j]);
}
}
output_grid(convergence_grid);
return 0;
}
void init_complex_grid(complex complex_grid[RES][RES],
double left, double right,
double top, double bottom) {
int i, j;
double restep = (top - bottom) / RES;
double imstep = (right - left) / RES;
for (i = 0; i < RES; i++) {
for (j = 0; j < RES; j++) {
complex_grid[i][j].re = left + j * imstep;
complex_grid[i][j].im = bottom + i * restep;
}
}
}
int converge(complex a) {
complex z = { 0, 0 };
int cnt = 0;
while (cnt <= MAX_DEPTH && mag_complex(z) <= 2) {
z = add_complex(square_complex(z), a);
cnt++;
}
return cnt;
}
complex add_complex(complex a, complex b) {
complex added = { a.re + b.re, a.im + b.im };
return added;
}
complex square_complex(complex a) {
complex b;
b.re = a.re * a.re - a.im * a.im;
b.im = 2 * a.re * b.im;
return b;
}
double mag_complex(complex a) {
return sqrt(a.re * a.re + a.im * a.im);
}
void output_grid(unsigned int grid[RES][RES]) {
FILE *f = fopen("mandelbrot.dat", "w");
int i, j;
for (i = 0; i < RES; i++) {
for (j = 0; j < RES; j++) {
fprintf(f, "%d ", grid[i][j]);
}
fprintf(f, "\n");
}
fclose(f);
printf("\nFILE CLOSED\n");
}
Я также добавил строку printf("\nFILE CLOSED\n");
, чтобы знать, что вывод был записан в файл, но это также не запускается с помощью RES > 321
.
Нужно ли мне тогда переписывать все с точки зрения указателей (например, *((a+i)) + j)) или я все еще могу использовать массивы, такие как a[i][j]?
Вы можете использовать нотацию массива для доступа к данным. На самом деле это обычный способ написания кода с использованием динамическая память.
fprintf(f, "%d ", grid[i][j]);
использует несоответствующий спецификатор преобразования, grid[i][j]
равно unsigned
(может быть преднамеренным)
Вы определяете слишком много данных с автоматическим хранением в функции main()
: либо делайте большие массивы глобальными, статическими, либо выделяйте их из кучи.
Вот простое решение, которое вы можете попробовать:
int main(void) {
int i, j;
static unsigned int convergence_grid[RES][RES];
static complex complex_grid[RES][RES];
init_complex_grid(complex_grid, -2.5, 1, 1, -1);
for (i = 0; i < RES; i++) {
for (j = 0; j < RES; j++) {
convergence_grid[i][j] = converge(complex_grid[i][j]);
}
}
output_grid(convergence_grid);
return 0;
}
Вот альтернатива с использованием распределения кучи:
int main(void) {
int i, j;
unsigned int (*convergence_grid)[RES] = calloc(sizeof(*convergence_grid), RES);
complex (*complex_grid)[RES] = calloc(sizeof(*complex_grid), RES);
if (!convergence_grid || !complex_grid) {
fprintf(stderr, "cannot allocate arrays\n");
return 1;
}
init_complex_grid(complex_grid, -2.5, 1, 1, -1);
for (i = 0; i < RES; i++) {
for (j = 0; j < RES; j++) {
convergence_grid[i][j] = converge(complex_grid[i][j]);
}
}
output_grid(convergence_grid);
free(complex_grid);
free(convergence_grid);
return 0;
}
Спасибо, static снова работал только до предела, но с помощью: c complex **complex_grid; complex_grid = malloc(RES*sizeof(complex*)); for(i=0;i<RES;i++){ complex_grid[i] = malloc(RES*sizeof(complex)); }
все разобрался
Существует разница между 2D-массивом, опубликованным в вопросе, и указателем на массив или указатели, как в вашем комментарии, которые требуют разных прототипов для других функций. Используйте определения из моего ответа, чтобы выделить реальные 2D-массивы из кучи и передать на них указатели.
Вероятно, у вас закончилось (куча) место. Может попробовать
malloc()
и друзей заcomplex_grid
?