0

I am trying to create a program that populates a fixed-size argument array using the arguments passed through the terminal. My first step is trying to create and populate the array of default argument strings, which I have succeeded in doing. However, I am now trying to use malloc() to allocate space for this array, and cannot get it to compile. I've tried everything I can think of regarding the proper syntax. I've tried doing more research into malloc() and how to use it for two dimensional arrays, but I haven't found any information that helps me. I'm stuck and not sure what to do next. Here is the code:

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#define MAX_NUM_OF_ARGS 5
#define MAX_ARG_SIZE 256

int main(int argc, char **argv) {
    printf("%s%d\n", "Length: ", argc); //for debug purposes

    // Make sure we don't have more than five arguments
    if(argc > MAX_NUM_OF_ARGS) {
        printf("%s", "Too many arguments. Must enter fewer than 4.");
    }
    // Populate the array
    else{
        char defaultArgs[] = "defaultArgs"; //create default argument array

        //allocate memory for default array
        char argumentArray[MAX_NUM_OF_ARGS][MAX_ARG_SIZE] =
            (char *)malloc(MAX_NUM_OF_ARGS * MAX_ARG_SIZE * sizeof(char));

        //populate array with default arguments
        for (int i = 0; i < MAX_NUM_OF_ARGS; i++) {
            strcpy(argumentArray[i], defaultArgs);
            printf("%s\n", argumentArray[i]);
        }

        free(argumentArray);
        return 0;
    }
}

When I try to compile I get an invalid initializer error at the (char*) cast for malloc(). I've tried casting it to (char**) and (char) and also changing the sizeof(char) to sizeof(char*) and sizeof(char**).

I am not really sure what I am doing wrong at this point and I am at a loss as far as what to even try next.

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
Blake Simmons
  • 426
  • 1
  • 8
  • 23
  • `char **argv` is declared in `main()`, but unused in code. Is that your intent? – chux - Reinstate Monica Sep 26 '18 at 21:08
  • @chux that will be used later on to poplate the array with arguments from the terminal. I haven't gotten that far yet. – Blake Simmons Sep 26 '18 at 21:19
  • Blake Simmons, still useful to consider [that](https://stackoverflow.com/questions/52525714/how-do-i-use-malloc-to-allocate-memory-to-store-an-array-of-strings?noredirect=1#comment91992147_52525714) now as in what should happen if `strlen(argv[i]) >= MAX_ARG_SIZE`? – chux - Reinstate Monica Sep 26 '18 at 21:33

3 Answers3

2

You've declared argumentArray as a two-dimensional array of char. The malloc function returns a pointer, so you can't assign a pointer to an element of this array.

You need a pointer to store what's being returned. Actually, in this case you need a pointer to a pointer, and you'll need to call malloc multiple times, once for an array of pointers for the arguments, then again in a loop for each argument:

char **argumentArray = malloc(MAX_NUM_OF_ARGS * sizeof(char *));

for (int i=0; i<MAX_NUM_OF_ARGS; i++) {
    argumentArray[i] = malloc(MAX_ARG_SIZE);
    strcpy(argumentArray[i], defaultArgs);
    printf("%s\n", argumentArray[i]);
}
dbush
  • 205,898
  • 23
  • 218
  • 273
2

You cannot store an array of strings in C, as a string is a variable-length datastructure, not a simple type.
So, decide what you want:

  1. An array of fixed-length buffers storing strings of fixed (maximum) length.

    char (*p)[MAX_LEN] = malloc(n * sizeof *p);
    // Store the strings at p[0], p[1], …, p[n - 1]
    
  2. A buffer storing any number of strings consecutively.

    char* p = malloc(sum_of_string_lengths + count_of_strings);
    // Now fill in the strings one after the other, including Terminator
    
  3. An array of pointers to strings.

    char** p = malloc(n * sizeof *p);
    p[0] = strdup(source[0]);
    // ...
    // p[n - 1] = ...
    

    With strdup() the common utility-function defined like:

    char* strdup(const char* s) {
        size_t n = strlen(s) + 1;
        char* r = malloc(n);
        if (r)
            memcpy(r, s, n);
        return r;
    }
    
Deduplicator
  • 44,692
  • 7
  • 66
  • 118
0

Try thinking about it like this:

  • Strings are character pointers
  • You need an array of character pointers

Here is an example where I make an array of char *. Essentially the pointer returned by malloc points to an area where char * will reside. Here is an illustration of what is going on.

/*
    malloc_ret_ptr  --->  [ char * my_str1 | char * my_str2 |  char * my_str3 ]
                                   |                |                 |
                                   |                |                 |
                                   v                v                 v
                                  "Thank"           "You"            "Chicago"
*/
    int main() {

          char * my_string = "this is my string";

          char ** my_string_array;

          my_string_array = malloc(sizeof(char*)*10); //Create an array of character pointers

          //Place char * inside of char * array
          my_string_array[0] = my_string;

          return 0;
        }
Carson Harmon
  • 319
  • 1
  • 8
  • Okay, I think I see what's going on here, but I'd like to ask some questions to clarify. First, why don't you need to cast malloc? Everywhere I look I am told that malloc needs to be cast to the datatype. Second, it seems like I'm just making space for the pointers themselves, rather than allocating space for the pointers and the strings that they point to. Is this not correct? – Blake Simmons Sep 26 '18 at 21:06
  • @BlakeSimmons "Everywhere I look I am told that malloc needs to be cast to the datatype" --> [Do I cast the result of malloc?](https://stackoverflow.com/q/605845/2410359). The cast is not needed. What is an example of a placed you looked? – chux - Reinstate Monica Sep 26 '18 at 21:09
  • Blake, you are correct in the fact that the malloc call I show in the picture is making space for the pointers. That is exactly what it is doing. The string I placed in the array is a string literal and I did not need to allocate space for it. If you ever do need to allocate space for a string, then you can call malloc to allocate space for the string, then store the pointer returned into the array. Hope that helps. – Carson Harmon Sep 26 '18 at 22:43