triple pointers, arrays, and malloc - c

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
}

Related

Expand a C array inside a function

This works in a main, but breaks when put into a function. I'm not sure how to reassign the pointer after passing into a function.
void expandArray(int** arr[], int* size) {
int *temp;
*temp = *arr;
*arr = (int*) malloc(*size * 2 * sizeof(int));
for (int i = 0; i < *size; i++) {
printf("assigning from temp: %d ", temp[i]);
arr[i] = temp[i];
printf("to arr: %d \n", arr[i]);
}
*size = *size * 2;
free(temp);
}
main(){
int *arr;
arr = (int*) malloc(maxSize * sizeof(int));
if ....
expandArray(arr, &arrSize);
// use bigger arr for other stuff
}
In main, arr is declared as int *arr. When main calls expandArray, it should pass a pointer to arr, which is written &arr and has type int **a.
However, you declared the parameter to expandArray as int **arr[], adding additional brackets. Those are unnecessary and change the type, and your compiler should have warned you about that. Pay attention to compiler warnings. Be sure you understand them, and resolve them before proceeding.
In expandArray, you use both arr[i] and temp[i] to access the array. However, arr[i] is not a correct way to access array elements. When the declaration of the arr parameter is corrected, it will be int **arr, and it will not be proper to refer to an element of the array as arr[i]. It will be (*arr)[i].
Commonly, to make this a little less confusion, authors will use a temporary variable to hold the pointer, so they do not need the extra asterisk:
int *NewArray = malloc(...); // Get new space.
*arr = NewArray; // Send new address to caller.
...
NewArray[i] = temp[i]; // Use temporary variable for access.
Some other points:
When calling malloc, use sizeof *p, where p is the pointer being assigned to, rather than sizeof(int). This is better because, if you later want to change the type for p, it only has to be changed in its declaration, not also in the sizeof. Then there is less likely to be a mistake where it is changed in one place and not another.
Do not cast the result of malloc. This is unnecessary in C, although it is required in C++.
main should be declared as int main(void) or int main(int argc, char *argv[]), not as main(). (C implementations may also provide for other forms.)
Use size_t for sizes of arrays, not int, and either size_t or ptrdiff_t for indices of arrays.
Overall, the code could be:
#include <stdio.h>
#include <stdlib.h>
void expandArray(int **arr, int *size)
{
// Record old pointer and size in temporary variables for convenience.
int *OldArray = arr;
size_t OldSize = *size;
// Prepare new size and pointer.
size_t NewSize = 2 * OldSize;
int *NewArray = malloc(NewSize * sizeof *NewArray);
// Handle allocation failure.
if (!NewArray)
{
fprintf(stderr, "Error, unable to allocate memory.\n");
exit(EXIT_FAILURE);
}
// Copy data from old array to new array.
for (size_t i = 0; i < OldSize; ++i)
NewArray[i] = OldArray[i];
// Send new size and pointer to caller.
*size = NewSize;
*arr = NewArray;
// Release old memory.
free(OldArray);
}
int main(void)
{
int *arr;
arr = malloc(InitialSize * sizeof *arr);
if (...)
expandArray(&arr, &arrSize);
// use bigger arr for other stuff
}
I think the arr sould be int ** type.
void expandArray(int** arr, int* size) {
int *temp;
temp = *arr;
*arr = (int*) malloc(*size * 2 * sizeof(int));
for (int i = 0; i < *size; i++) {
printf("assigning from temp: %d ", temp[i]);
(*arr)[i] = temp[i];
printf("to arr: %d \n", (*arr)[i]);
}
*size = *size * 2;
free(temp);
}
If you just want to expand the array size, you can use realloc.
And the extended area should be initialized using memset.
void expandArray(int** arr, int* size) {
*arr = (int*) realloc(*arr, *size * 2 * sizeof(int));
memset(*arr+*size, 0, *size * sizeof(int));
*size = *size * 2;
}

How to compare two strings, which(both of them) are stored in char double pointer?

char ** magazine;
char ** ransom;
*magazine = malloc(sizeof(char*) * m);
for(int magazine_i = 0; magazine_i < m; magazine_i++){
magazine[magazine_i] = (char *)malloc(10240 * sizeof(char));
scanf("%s",magazine[magazine_i]);
}
*ransom = malloc(sizeof(char*) * n);
for(int ransom_i = 0; ransom_i < n; ransom_i++){
ransom[ransom_i] = (char *)malloc(10240 * sizeof(char));
scanf("%s",ransom[ransom_i]);
}
Now I want to compare the string stored in ransom to magazine. How it can be done? Please help
You can use strcmp in a loop:
for (i = 0; i < n; i++) {
if (strcmp(magazine[i], ransom[i]) == 0) {
...
}
}
But if (as the title suggests) ransom is declared as a pointer to pointer to char:
char **ransom;
you don't want the dereference operator *
*ransom = malloc(sizeof(char*) * n);
should be
ransom = malloc(sizeof(char*) * n);

Allocating memory for pointer to pointer to pointer in C

I am trying to allocate memory for triple pointer and I cannot make it right. I have pointer to pointer to char
char **words;
allocate(&words);
And I created method for memory allocation:
void allocate(char ***words){
for (int i = 0; i < MAXWORDNUM; ++i)
(*words)[i] = malloc(sizeof(char*) * MAXWORDNUM);
for (int i = 0; i < MAXWORD; ++i)
(**words)[i] = malloc(sizeof(char) * MAXWORD);
}
As I understand I should allocate memory for pointers and then I should allocate memory for each char. For the above code I am getting error:
warning: incompatible pointer to integer conversion assigning
to 'char' from 'void *' [-Wint-conversion]
(**words)[i] = malloc(sizeof(char) * MAXWORD);
How to make it work?
Thank you
void allocate(char ***words){
*words = malloc(sizeof(char*) * MAXWORDNUM);
for (int i = 0; i < MAXWORDNUM; ++i)
(*words)[i] = malloc(MAXWORD);
}
You want an array of pointers, not an array of array of pointers, the first loop is not needed:
void allocate(char ***words){
/* for (int i = 0; i < MAXWORDNUM; ++i) */
/* (m)allocate space for n pointers to words */
*words = malloc(sizeof(char *) * MAXWORDNUM);
for (int i = 0; i < MAXWORDNUM; ++i)
(*words)[i] = malloc(MAXWORD); /* (m)allocate space for each word */
}
int main(void)
{
char **words;
allocate(&words);
return 0;
}
It depends on your purpose, do you intend to create a 2-dimensional array, or a array of pointers, or just a pointer to pointer?
1) A 2-dimensional array
void allocate_two_dimen_array(char ***words, unsigned int x, unsigned int y){
*word = malloc(x * y * sizeof(char));
}
2) A array of char pointers
void allocate_pointer_array(char ***words, unsigned int quantity){
*word = malloc(quantity * sizeof(char*));
}
3) A pure pointer to char pointer
void allocate_pointer_pointer(char ***words){
*word = malloc(sizeof(char**));
}
For practical purposes, for instance: the first one can be used to store a bmp image, the second one is used to store a set of strings
word = {"This is the first line", "This is the second line"};

Assigning a value to a 2-d array in a struct is segfaulting

Here's the code:
typedef struct _Matrix {
int rows;
int cols;
int** elements;
} Matrix;
int main(int argc, char* argv[])
{
Matrix *matrix1;
matrix1 = malloc(sizeof(Matrix));
matrix1->rows = 2;
matrix1->cols = 2;
matrix1->elements = malloc(sizeof(int) * 4);
matrix1->elements[0][0] = 1;
matrix1->elements[0][1] = 2;
matrix1->elements[1][0] = 3;
matrix1->elements[1][1] = 4;
}
I'm not sure what I'm missing here. matrix1->elements should be a 2d array/pointer and I'm just trying to assign values to that array.
It segfaults at this line: matrix1->elements[0][0] = 1;
Replace the line:
matrix1->elements = malloc(sizeof(int) * 4);
by
matrix1->elements = malloc(sizeof(int*) * 2);
matrix1->elements[0] = malloc(sizeof(int) * 2);
matrix1->elements[1] = malloc(sizeof(int) * 2);
The first line allocates memory for 4 ints. When you use element[0] on that memory, you are treating an int like it is an int*. There are a series of problems when you do that.
The correct approach is:
Allocate memory for 2 int*.
Allocate memory for each of those int* to hold the ints.

Return 2 dimension array in C function

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.

Resources