I want to write a function in C language which returns the 2 dimension array to my main function.
A function that returns a dynamically allocated two dimensional array for the int type.
int ** myfunc(size_t width, size_t height)
{
return malloc(width * height * sizeof(int));
}
It has to be deleted with free once it is not used anymore.
EDIT This only allocates the space for the array which could be accessed by pointer arithmetic but unfortunately not by the index operators like array[x][y].
If you want something like this here is a good explanation. It boils down to something like this:
int ** myfunc(size_t ncolumns, size_t nrows)
{
int **array;
array = malloc(nrows * sizeof(int *));
for(i = 0; i < nrows; i++)
{
array[i] = malloc(ncolumns * sizeof(int));
}
}
You can not simply return malloc( x * y * sizeof(type) );
This will produce a segmentation fault when you try to index the array as a 2 dimensional array.
int **a = malloc(10 * 10 * sizeof(int));
a[1][0] = 123;
a[0][1] = 321;
The result of the above: Segmentation fault
You need to first create an array of pointers with c/malloc() then iterate this array of pointers and allocate space for the width for each of them.
void *calloc2d(size_t x, size_t y, size_t elem_size) {
void **p = calloc(y, sizeof(void*));
if(!p) return NULL;
for(int i = 0; i < y; i++) {
p[i] = calloc(x, elem_size);
if(!p[i]) {
free2d(y, p);
return NULL;
}
}
return (void*)p;
}
And free
void free2d(size_t y, void *matrix) {
if(!matrix) return;
void **m = matrix;
for(int i = 0; i < y; i++) {
if(m[i]) free(m[i]);
}
free(m);
return;
}
It should be simple i guess...
char **functioName(char param[][20])
{
char[][20] temp = malloc(20 * 20 * sizeof char);
//processing
return temp
}
If you know the size of the array, you can do so:
int (*myfunc())[10] {
int (*ret)[10]=malloc(10*10*sizeof(int));
return ret;
}
This function return pointer to 10 arrays of 10 ints.
Of course, you should use it as it is, and don't forget to free it after using.
Related
I'm trying to code a resizable array, which expands when it's full. All functions are working, but the resize one isn't.
int main(void)
{
int arr[4];
int *ptr = arr;
initializeEmptyArray(ptr);
insertAtIndex(ptr, 0, 4);
insertAtIndex(ptr, 0, 3);
insertAtIndex(ptr, 0, 2);
insertAtIndex(ptr, 0, 1);
resizeArray(&ptr);
for (int i = 0; i < capacity; i++)
{
printf("%i", arr[i]);
}
}
This initiates my array [1,2,3,4] and then calls the resize array to test it.
void resizeArray(int **arr)
{
int *newArr = (int *)malloc(capacity * 2 * sizeof(int));
for (int i = 0; i < capacity; i++)
{
newArr[i] = (*arr)[i];
}
for (int i = capacity; i < capacity * 2; i++)
{
newArr[i] = EMPTY;
}
free(*arr);
*arr = newArr;
}
The problem is the value of arr when I print it doesn't change to [1,2,3,4,-1,-1,-1,-1] (-1 represents empty). How can I change the pointer to point to this new array?
Capacity stands for the number of elements the array support, initiated as 4
EMPTY is defined as -1, to represent a empty slot in the array.
The two main issues with the code is that arr is allocated on the stack in main(), and then you free() it in resizerArray(). That is a defect, and I fixed that my heap allocating arr in main() instead. In your loop, you print arr[i] but pass ptr to resizeArray() which is updated, but arr still points to memory that is now free'ed. I fixed this issue by eliminated the ptr variable:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define EMPTY 0
void resizeArray(int **arr, size_t capacity) {
int *newArr = malloc(2 * capacity * sizeof(int));
// for (int i = 0; i < 2 * capacity; i++) {
// newArr[i] = i < capacity ? (*arr)[i] : EMPTY;
// }
memcpy(newArr, *arr, capacity * sizeof(int));
memset(newArr + capacity, EMPTY, capacity * sizeof(int));
free(*arr);
*arr = newArr;
}
int main(void) {
size_t capacity = 4;
int *arr = malloc(capacity * sizeof(int));
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
arr[3] = 4;
for (int i = 0; i < capacity; i++) {
printf("before: %d\n", arr[i]);
}
resizeArray(&arr, capacity);
capacity *= 2;
for (int i = 0; i < capacity; i++) {
printf("after: %d\n", arr[i]);
}
}
I comment out the loop in resizeArray so you can see how you would do that. The code prints:
before: 1
before: 2
before: 3
before: 4
after: 1
after: 2
after: 3
after: 4
after: 0
after: 0
after: 0
after: 0
Both resizeArray() and the calling code has to know about the factor 2. This is not a great design. Maybe pass in old and new capacity? Or pass in size_t *capacity that can be updated if you want to hard-code the factor in resizeArray()? Remember to check the return value of malloc() to ensure it did not fail.
See realloc() for the standard way to resize heap allocated memory, and calloc() for how to get pre-initialized memory.
You can't resize an array. It's size is fixed.
So if you want something that can be resized do:
int arr[4]; --> int* arr = malloc(4 * sizeof *arr);
BTW:
It seems you miss a line like:
capacity = 2 * capacity ;
Hava a look at "realloc", your question sounds like a perfect match
You can not resize an array with automatic storage duration. You can do this with arrays that have allocated storage duration.
So you should remove the array declaration in main and write
int *ptr = malloc( 4 * sizeof( int ) );
or
int *ptr = malloc( capacity * sizeof( int ) );
Also you forgot to change the value of the variable capacity. I suppose that it is not declared as a constant variable.
In this case the function resizeArray can look for example the following way
int resizeArray( int **arr )
{
int *newArr = realloc( *arr, capacity * 2 * sizeof(int));
int success = newArr != NULL;
if ( success )
{
*arr = newArr;
for (int i = capacity; i < capacity * 2; i++)
{
newArr[i] = EMPTY;
}
capacity *= 2;
}
return success;
}
Pay attention to that a reallocation of the array can fail. So the function should signal to the caller whether the reallocation was successful.
Also it is not a good idea to use the variable capacity as a global variable.
You could write in main
int capacity = 4;
int *ptr = malloc( capacity * sizeof( int ) );
// ...
and call the function like
resizeArray( &ptr, &capacity );
In this case the function will look the following way
int resizeArray( int **arr, int *capacity )
{
int *newArr = realloc( *arr, *capacity * 2 * sizeof(int));
int success = newArr != NULL;
if ( success )
{
*arr = newArr;
for (int i = *capacity; i < *capacity * 2; i++)
{
newArr[i] = EMPTY;
}
*capacity *= 2;
}
return success;
}
I am trying to dynamically allocate an array, put some data in it, and then free it and set the array pointer to null so that it can not be accessed in the future. Also, unrelated, but I am storing the size of the array in the first element and then passing it back indexed one up, it is part of the assignment, so hopefully that doesn't confuse anyone.
If I am understanding the error correctly, I am trying to call free() on the array that my malloc'ed array was copied in to. This is not allowed because free() is not being called on the actual malloc'ed array but rather the one that's holding its values.
If this is the case, how would I fix my call of free() to only receive an array address and dereference it like free(*array);. Right now I have some mess of asteriscs and a cast and I have no idea why it works. If you know how to fix the free call into the above or just explain why what I have now works, I would greatly appreciate it. My goal is to be able to set the parameter for the custom free function to a void pointer instead of a specific data type pointer. Thanks!!
#include <stdlib.h>
int getSizeArray(void *array);
void * createArray(int n, int sizeOfDatatype);
void freeArray(double ** array);
int main(void){
double * arr = createArray(10, sizeof(double));
int size = getSizeArray(arr);
/* using output for error checking
for(int i = 0; i < 10; i++){
arr[i] = i;
}
for(int j = 0; j < 10; j++){
printf("%f\n", arr[j]);
}
*/
void* p = &arr;
freeArray(p);
}
int getSizeArray(void *array){
int s = ((int *) array)[-1];
return s;
}
void * createArray(int n, int sizeOfDatatype){
int * array = malloc((n * sizeOfDatatype) + sizeof(int));
array[0] = n;
return (void*) (array + 1);
}
void freeArray(double ** array){
free(*array);
*array = NULL;
}
EDIT: Look to #JonathanLeffler comment. The issue is with alignment. I switched around some of my code but I had to index back one and not cast in my functions but instead in main
#include <stdlib.h>
int getSizeArray(void *array);
void * createArray(int n, int sizeOfDatatype);
void freeArray(double ** array);
int main(void){
double * arr = createArray(10, sizeof(double));
arr = (void*) (arr + 1);
int size = getSizeArray(arr);
/* using output for error checking*/
for(int i = 0; i < 10; i++){
arr[i] = i;
}
for(int j = 0; j < 10; j++){
printf("%f\n", arr[j]);
}
arr = (double*) (arr - 1);
freeArray(&arr);
for(int j = 0; j < 10; j++){
printf("%f\n", arr[j]);
}
}
int getSizeArray(void *array){
int s = ((int *) array)[-1];
return s;
}
void * createArray(int n, int sizeOfDatatype){
int * array = malloc((n * sizeOfDatatype) + sizeof(int));
array[0] = n;
return array;
}
void freeArray(double ** array){
free(*array);
*array = NULL;
}
I provided a complete solution to this problem for another user. Must be a class assignment. My version is very similar to yours except I used macros instead of functions. Anyway, #Serge answer was so close. It -1 not +1.
Here what I plug into my code and it worked fine:
void freeArray(void** array)
{
free( ((int*)(*array)) - 1 );
*array = NULL;
}
Let me explain what going on. The C allocation routines are basically doing what you are doing. They save the array size one word above the actual array. Follow link for more information on how free() works. In our version, we are saving the array size one int (2 words/4 bytes) above the actual array. Your code was wrong because the address you reference is the 3rd element and not the first. You need to pass in the address where the array allocation originated which is ((int*)(*array)) - 1.
If you free(*array), you don't need to *array = NULL after that.
Also, you can't cast a (void *) onto an (int *) and assign it to a (double *).
Lastly, you can't freeArray(p); if p is a single pointer since freeArray(double ** array) has a parameter of double double-pointer.
Hopefully, this helps.
You can compare my modified code.
#include <stdlib.h>
#include <stdio.h>
int getSizeArray(void *array);
void * createArray(int n, int sizeOfDatatype);
void freeArray(void ** array);
int main(void){
double * arr = (double *)createArray(10, sizeof(double));
int size = getSizeArray(arr);
printf("size of arr %d\n", size);
// using output for error checking
for(int i = 0; i < 10; i++){
arr[i] = i;
}
for(int j = 0; j < 10; j++){
printf("%f\n", arr[j]);
}
void ** p = (void **)&arr;
freeArray(p);
printf("del arr, then arr = %u\n",(unsigned)arr);
}
int getSizeArray(void *array){
int s = ((int *) array)[-1];
return s;
}
void * createArray(int n, int sizeOfDatatype){
int * array = (int*)malloc((n * sizeOfDatatype) + sizeof(int));
array[0] = n;
return (void*) (array + 1);
}
void freeArray(void ** array){
free(((int*)*array)-1);
*array = NULL;
}
output:
size of arr 10
0.000000
1.000000
2.000000
3.000000
4.000000
5.000000
6.000000
7.000000
8.000000
9.000000
del arr, then arr = 0
I'm using an example from https://phoxis.org/2012/07/12/get-sorted-index-orderting-of-an-array/ where he returns the sort indices from a sort of an array, i.e.
3,4,2,6,8 returns 4,3,1,0,2 (+1 for each index in R). This is the equivalent of R's order function
I've translated his/her code to work as a function returning an array of sorted indices. The code gives the correct answer.
keeping track of the original indices of an array after sorting in C has a similar response, but as #BLUEPIXY warns, his solution doesn't work in all circumstances. I need something that will work in all circumstances, including ties.
however, the original author uses a global pointer, which causes a memory leak, and free() doesn't fix it. which I don't know how to do this without the global pointer.
How can I fix this memory leak, or at least return sorted indices in C that will always work?
#include <stdio.h>
#include <stdlib.h>
/* holds the address of the array of which the sorted index
* order needs to be found
*/
int * base_arr = NULL;
/* Note how the compare function compares the values of the
* array to be sorted. The passed value to this function
* by `qsort' are actually the `idx' array elements.
*/
static int compar_increase (const void * a, const void * b) {
int aa = *((int * ) a), bb = *((int *) b);
if (base_arr[aa] < base_arr[bb]) {
return 1;
} else if (base_arr[aa] == base_arr[bb]) {
return 0;
} else {
// if (base_arr[aa] > base_arr[bb])
return -1;
}
}
int * order_int (const int * ARRAY, const size_t SIZE) {
int * idx = malloc(SIZE * sizeof(int));
base_arr = malloc(sizeof(int) * SIZE);
for (size_t i = 0; i < SIZE; i++) {
base_arr[i] = ARRAY[i];
idx[i] = i;
}
qsort(idx, SIZE, sizeof(int), compar_increase);
free(base_arr); base_arr = NULL;
return idx;
}
int main () {
const int a[] = {3,4,2,6,8};
int * b = malloc(sizeof(int) * sizeof(a) / sizeof (*a));
b = order_int(a, sizeof(a) / sizeof(*a));
for (size_t i = 0; i < sizeof(a)/sizeof(*a); i++) {
printf("b[%lu] = %d\n", i, b[i]+1);
}
free(b); b = NULL;
return 0;
}
A straightforward approach without using a global variable can look the following way
#include <stdio.h>
#include <stdlib.h>
int cmp_ptr(const void *a, const void *b)
{
const int **left = (const int **)a;
const int **right = (const int **)b;
return (**left < **right) - (**right < **left);
}
size_t * order_int(const int *a, size_t n)
{
const int **pointers = malloc(n * sizeof(const int *));
for (size_t i = 0; i < n; i++) pointers[i] = a + i;
qsort(pointers, n, sizeof(const int *), cmp_ptr);
size_t *indices = malloc(n * sizeof(size_t));
for (size_t i = 0; i < n; i++) indices[i] = pointers[i] - a;
free(pointers);
return indices;
}
int main( void )
{
const int a[] = { 3,4,2,6,8 };
const size_t N = sizeof(a) / sizeof(*a);
size_t *indices = order_int(a, N);
for (size_t i = 0; i < N; i++) printf("%d ", a[indices[i]]);
putchar('\n');
free(indices);
return 0;
}
The program output is
8 6 4 3 2
As for the memory leak then it is due to overwriting the value of the pointer to redundantly allocated memory.
int * b = malloc(sizeof(int) * sizeof(a) / sizeof (*a));
b = order_int(a, sizeof(a) / sizeof(*a));
The memory allocation does not make sense.
The problem I see is that within main function - you are allocating pointer b some memory -
int * b = malloc(sizeof(int) * sizeof(a) / sizeof (*a));
The next line calls order_int(...) that returns a pointer to already allocated memory -
b = order_int(a, sizeof(a) / sizeof(*a));
Looking at the order_int function -
int * order_int (const int * ARRAY, const size_t SIZE) {
int * idx = malloc(SIZE * sizeof(int));
base_arr = malloc(sizeof(int) * SIZE);
for (size_t i = 0; i < SIZE; i++) {
base_arr[i] = ARRAY[i];
idx[i] = i;
}
qsort(idx, SIZE, sizeof(int), compar_increase);
free(base_arr); base_arr = NULL;
return idx;
}
.. you see that idx has been already been allocated the correct memory.
I would suggest removing the malloc from b - see below.
int * b = NULL;
My code compiles just fine, but I'm still a little rough on the pointer and array concepts. I would appreciate your help very much.
void initialize(int individual_count, int family_count, char ***indiIDs,
char ***names, char ***spousesIDs, char ***childIDs)
//so here I declared two int variables and four triple pointers,
// which are pointer to a pointer to a pointer to an integer, correct?
{
int i;
//malloc allocates memory space and returns the address of the
// first byte to the pointer *indiIDs,right?
(*indiIDs) = (char**)malloc(sizeof(char*) * individual_count);
(*names) = (char**)malloc(sizeof(char*) * individual_count);
for(i = 0; i <individual_count; i++)
{
(*indiIDs)[i] = (char*)malloc(sizeof(char) * 20);
(*names)[i] = NULL;
}
//*indiIDs[i] is an array of pointers, correct? so what exactly
// is the difference between mallocing and returning to *indiIDs
// and then to *indiIDs[i] as seen here?
(*spousesIDs) = (char**)malloc(sizeof(char*) * family_count);
(*childIDs) = (char**)malloc(sizeof(char*) * family_count);
for(i = 0; i < family_count; i++)
{
(*spousesIDs)[i] = (char*)malloc(sizeof(char) * 40);
//since spousesIDs[][] is a 2D array, would *spousesIDs[][]
// indicate a triple array then?
(*spousesIDs)[i][0] = '\0';
(*childIDs)[i] = NULL;
}
}
Your example doesn't show a 3D array, but a 2D array:
void init2D(char * ** x, int w, int h)
{
(*x) = (char**)malloc(sizeof(char*) * w);
for (i=0; i<w; i++) (*x)[i] = (char*)malloc(sizeof(char) * h);
}
The reason it has an additional * as a function parameter, is because C doesn't have pass-by-refence like C++
It's used this way:
void main ()
{
char ** lines = 0;
init2D (&lines, 4, 256); // char[256] x 4
}
I am new to C and during my learning I want to return a two dimensional array from a function, so that I can use it in my main program. Can anyone explain me the same with example. Thanks in advance.
It depends how it is implemented. You can either work with just a one-dimensional array where you know the length of each (row) and the next row begins immediately after the previous one. OR, you can have an array of pointers to arrays. The extra cost though is you need to de-reference two pointers to get to one element of data.
// 2D array of data, with just one array
char* get_2d_ex1(int rows, int cols) {
int r, c, idx;
char* p = malloc(rows*cols);
for (r=0; r<rows; r++) {
for (c=0; c<cols; c++) {
idx = r*cols + c; // this is key
p[idx] = c; // put the col# in its place, for example.
}
}
return p;
}
Declare your function as returning a pointer to a pointer. If we use int as an example:
int **samplefunction() {
int** retval = new int*[100];
for (int i = 1; i < 100; i++) {
retval[i] = new int[100];
}
// do stuff here to retval[i][j]
return retval;
}
Here's an example of how you might create, manipulate and free a "2d array":
#include <stdlib.h>
#define ROWS 5
#define COLS 10
int **create_2d_array(size_t rows, size_t cols)
{
size_t i;
int **array = (int**)malloc(rows * sizeof(int*));
for (i = 0; i < rows; i++)
array[i] = (int*)malloc(cols * sizeof(int));
return array;
}
void free_2d_array(int **array, size_t rows, size_t cols)
{
size_t i;
for (i = 0; i < rows; i++)
free(array[i]);
free(array);
}
int main(void)
{
int **array2d = create_2d_array(ROWS, COLS);
/* ... */
array2d[3][4] = 5;
/* ... */
free_2d_array(array2d, ROWS, COLS);
return 0;
}
To create a "2d array"/matrix, all you have to do is create a dynamic array of pointers (in this case int*) of the size of the rows/width:
int **array = (int**)malloc(rows * sizeof(int*));
Then you set each of those pointers to point to a dynamic array of int of the size of the columns/height:
array[i] = (int*)malloc(cols * sizeof(int));
Note that the casts on malloc aren't required, it's just a habit I have.