2

I am currently trying to learn C and I have come to a problem that I've been unable to solve.

Consider:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define ELEMENTS 5

void make(char **array, int *array_size) {
    int i;
    char *t = "Hello, World!";

    array = malloc(ELEMENTS * sizeof(char *));

    for (i = 0; i < ELEMENTS; ++i) {
        array[i] = malloc(strlen(t) + 1 * sizeof(char));
        array[i] = strdup(t);
    }
}

int main(int argc, char **argv) {
    char **array;
    int size;
    int i;

    make(array, &size);

    for (i = 0; i < size; ++i) {
        printf("%s\n", array[i]);
    }

    return 0;
}

I have no idea why the above fails to read back the contents of the array after creating it. I have literally spent an hour trying to understand why it fails but have come up empty handed. No doubt it's something trivial.

Cheers,

1
  • Technically, what you have are not "multi-dimensional arrays". You have an array of pointers, each of which points to the beginning of a smaller-dimension array. "Multi-dimensional array" refers to something different, with all the memory allocated contiguously. Commented May 1, 2009 at 4:15

5 Answers 5

6

You need to pass the address of "array" into the function. That is, you need char ***. This is because you need to change the value of array, by allocating memory to it.

EDIT: Just to make it more complete, in the function declaration you need to have something like

void make(char ***array, int *array_size)

Then you need to call it using

make(&array, &size);

Inside the function make, allocate memory with

*array = malloc(ELEMENTS * sizeof(char *));

And change other places accordingly.

Also, as kauppi has pointed out, strdup will allocate memory for you, so you don't need to do malloc on each string.

Sign up to request clarification or add additional context in comments.

Comments

5

Here is the working code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define ELEMENTS 5

void make(char ***array) {
    char *t = "Hello, World!";

    *array = malloc(ELEMENTS * sizeof(char *));

    int i;
    for (i = 0; i < ELEMENTS; ++i) {
        (*array)[i] = strdup(t);
    }
}

int main(int argc, char **argv) {
    char **array;
    make(&array);

    int i;
    for (i = 0; i < ELEMENTS; ++i) {
        printf("%s\n", array[i]);
        free(array[i]);
    }
    free(array);
    return 0;
}

As the other have posted - there was unused size, and strdup allocates memory by itself, and it is nice to free the memory afterwards...

8 Comments

In standard C I don't think you can declare 'int i' after the call to make(&array) (or again after the malloc in the make() function).
I compiled it using default gcc options. I thinks this was added to the standard long time ago... But I can't decalare int inside the loop without -C99...
Even compiling with: gcc arr.c -Wall -strict -ansi or gcc arr.c -std=c88 works without any warnings or errors
gcc arr.c -std=c89 of course ;) -std=c88 wont run the compiler ;P
Remember to free the array, too, not just the strings in the array.
|
4

See PolyThinker's comment which is absolutely spot on.

In addition to the way you pass the array, you should check a few other issues:

  1. Perhaps you should assign something to array_size in make(...)?
  2. strdup(char*) allocates memory, the malloc for array[i] is not necessary.
  3. You should free all the memory you allocate after you don't need it anymore.

Comments

3

You are passing the current value of array to make as a copy (on the stack). when you change array in make(), you're only changing the copy, not the actual variable. Try passing by reference with &, or make it a char *** and work with *array = ...

Comments

0

size is declared but gets no value assigned (that should happen in function make, I suppose).

Comments

Your Answer

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