0

The project I am currently working on requires four dynamically created arrays of strings (each string no longer than 50 chars). So, I am trying to write a function that takes a pointer to a pointer and dynamically allocates memory for that variable.

This is as far as I've gotten:

void makeArray(char*** arr[], int n) {
 int i;
 *arr = malloc(n*sizeof(char*));
 for (i = 0; i<n; i++) {
 *arr[i] = malloc(sizeof(char)*50);
 }
}
int main() {
 char** test;
 makeArray(&test,4);
 return 0;
}

When I compile and run, I get this error:

main.c:16:13: warning: passing argument 1 of ‘makeArray’ from incompatible pointer type [-Wincompatible-pointer-types]
 makeArray(&test,4);
 ^
main.c:4:6: note: expected ‘char ****’ but argument is of type ‘char ***’
 void makeArray(char*** arr[], int n) {

When I use C Tutor, the function appears to successfully take in my test array and allocate 4 pointer slots. Then it successfully allocates 50 chars to the 0th test slot. However, when the loop runs again, I get an error. enter image description here

I've been stuck on this for two days now, so I welcome any suggestions the kind users of Stack Overflow may have!

asked Feb 5, 2020 at 23:00
8
  • OMG, a three star programmer! Question: why does the function return void? Commented Feb 5, 2020 at 23:14
  • When I see char*** x[] I see four stars. That's a ridiculous level of pointerism. Try and keep it to two at most, three if absolutely, unfortunately necessary. Commented Feb 5, 2020 at 23:16
  • Even worse, char ***arr[][ is beyond my grasp. Commented Feb 5, 2020 at 23:18
  • The function just modifies the array in place, so it doesn't need to return anything. And I stole the *** from here. Commented Feb 5, 2020 at 23:18
  • 2
    @chadathin Read this question and the answers: Correctly allocating multi-dimensional arrays It will help explain what you're actually doing when you call nested loops around malloc() to create "arrays". You're not really creating multidimsional arrays when you do that. You are really creating arrays of pointers to arrays of pointers to one-dimensional arrays of values. Nested allocation can also be very slow for large n-dimensional "arrays". Commented Feb 5, 2020 at 23:28

3 Answers 3

3
#include <stdio.h>
#include <stdlib.h>
void makeArray(char*** arr, int n) {
 int i;
 *arr = calloc(n, sizeof (char*));
 for (i = 0; i<n; i++) 
 {
 (*arr)[i] = calloc(50, sizeof(char));
 }
}
int main() {
 char **test;
 makeArray(&test,4);
 return 0;
}

Should be what you are looking for. How does it work:

  • First I changed your prototype to "char ***" as "char ***arr[]* as actally char****
  • Second *arr (allows writting to your variable test in main)
  • Third a little bit tricky (*arr) to write to test and than [] to use test as array.

I use calloc instead of malloc as it looks from my point of view better than malloc for a array and it ensurs your strings are initialized with 0 (zero-terminated)

answered Feb 5, 2020 at 23:22
Sign up to request clarification or add additional context in comments.

1 Comment

That's the ticket! Thank you so much for helping me understand your modifications in the process! And actually, our instructor covered malloc heavily and just kind of 'glazed over' calloc so I'll have to check out the man pages for that. Thank you again!
1

Here I took the solution from Schafwolle (a very soft and smooth nickname!) and mixed in my former solution and my idead of returning the allocated array. Do not forget to free the memory in the opposite order.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_STRING_SIZE 50
char** makeArray(int n) {
 int i;
 char** arr = calloc(n, sizeof (char*));
 for (i = 0; i<n; i++) 
 {
 arr[i] = calloc(MAX_STRING_SIZE, sizeof(char));
 }
 return arr;
}
void recycleArray(char** arr, int n) {
 int i;
 for (i = 0; i<n; i++) 
 {
 free(arr[i]);
 }
 free(arr);
}
int main() {
 char** test = makeArray(4);
 strncpy(test[0],"Have ", MAX_STRING_SIZE-1);
 strncpy(test[1],"a ", MAX_STRING_SIZE-1);
 strncpy(test[2],"nice ", MAX_STRING_SIZE-1);
 strncpy(test[3],"evening.", MAX_STRING_SIZE-1);
 printf("%s%s%s%s\n", test[0], test[1], test[2], test[3]);
 recycleArray(test, 4);
 return 0;
}
answered Feb 5, 2020 at 23:54

1 Comment

Oh, wow. This is great! I never even thought of just returning the char** and assigning that to a pointer. Thank you!
0

Just start with this:

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define MAX_STRING_SIZE 50
void makeArray(char* arr[], int n) {
 int i;
 for (i = 0; i<n; i++) {
 arr[i] = malloc(sizeof(char)*MAX_STRING_SIZE);
 }
}
int main() {
 char* test[4];
 makeArray(test,4);
 strncpy(test[0],"Have ", MAX_STRING_SIZE-1);
 strncpy(test[1],"a ", MAX_STRING_SIZE-1);
 strncpy(test[2],"nice ", MAX_STRING_SIZE-1);
 strncpy(test[3],"evening.", MAX_STRING_SIZE-1);
 printf("%s%s%s%s\n", test[0], test[1], test[2], test[3]);
 return 0;
}

If you also want to create the array of pointers dynamically, just return a pointer instead of void. This makes it more readable...

answered Feb 5, 2020 at 23:25

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.