Well, it obvious you are quite lost regarding how to return an allocated grid (pointer-to-pointer-to-int) from ft_ultimate_range()
to main()
.
To begin, you do not need to pass range
as a parameter to ft_ultimate_range()
. Instead, make the return type int **
and declare int **range
within ft_ultimate_range()
and then allocate len
pointers, and then allocate len
integers per-pointer, assign the values and then return range
and assign it to arr
in main()
, e.g.
#include <stdio.h>
#include <stdlib.h>
/* allocate a grid of [n][n] with numbers ranging max-min */
int **ft_ultimate_range (int min, int max)
{
int len = max - min,
**range = NULL,
count = min;
/* allocate len pointers */
range = malloc (len * sizeof * range);
if (!range) { /* validate EVERY allocation */
perror ("malloc-range");
return NULL;
}
/* allocate len int per-pointer */
for (int i = 0; i < len; i++) {
range[i] = malloc (len * sizeof *range[i]);
if (!range[i]) { /* validate alloation */
perror ("malloc-range[i]");
while (i--) /* free previously allocated rows */
free (range[i]); /* free pointers */
free (range);
return NULL;
}
}
/* assign values to allocated memory location */
for(int i = 0; i < len; i++) {
for(int j = 0; j < len; j++) {
range[i][j] = count++;
}
count = min;
}
return range;
}
(note: you MUST VALIDATE EVERY ALLOCATION...)
In main()
, you don't need ptr
, all you need is the int**
pointer you will assign the return from ft_ultimate_range()
to, e.g.
int main (void) {
int n = 6 - 3;
int **arr;
arr = ft_ultimate_range (3, 6);
if (!arr) /* validate return */
return 1;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
printf (" %d", arr[i][j]);
}
putchar ('\n');
free (arr[i]);
}
free (arr);
return 0;
}
(note: similarly, you must validate the return of ft_ultimate_range()
before blindly looping through the values (that will not be there if an allocation failed)).
Example Use/Output
$ ./bin/alloc_a_grid
3 4 5
3 4 5
3 4 5
Memory Use/Error Check
In any code you write that dynamically allocates memory, you have 2 responsibilities regarding any block of memory allocated: (1) always preserve a pointer to the starting address for the block of memory so, (2) it can be freed when it is no longer needed.
It is imperative that you use a memory error checking program to insure you do not attempt to access memory or write beyond/outside the bounds of your allocated block, attempt to read or base a conditional jump on an uninitialized value, and finally, to confirm that you free all the memory you have allocated.
For Linux valgrind
is the normal choice. There are similar memory checkers for every platform. They are all simple to use, just run your program through it.
$ valgrind ./bin/alloc_a_grid
==29026== Memcheck, a memory error detector
==29026== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==29026== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==29026== Command: ./bin/alloc_a_grid
==29026==
3 4 5
3 4 5
3 4 5
==29026==
==29026== HEAP SUMMARY:
==29026== in use at exit: 0 bytes in 0 blocks
==29026== total heap usage: 4 allocs, 4 frees, 60 bytes allocated
==29026==
==29026== All heap blocks were freed -- no leaks are possible
==29026==
==29026== For counts of detected and suppressed errors, rerun with: -v
==29026== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Always confirm that you have freed all memory you have allocated and that there are no memory errors.
Look things over and let me know if you have further questions.