Search code examples
cvoid-pointers

How to "rebuild" a decayed **char?


The following code is a simplified version of my larger program to demonstrate the problem.

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

const int m = 5;
char **words1;
char **words2;

void f(void *v) {
    printf("v: %p\n", v);

    int len = v==words1 ? 3 : 4;
    printf("len: %d\n", len);

    for (int i=0; i<m; i++) {
        // What goes here?
        /*
        char *c = malloc(sizeof(char) * len);
        c = (char*)v; // Something _like_ this?!
        printf("%s\n", c);
        */
    }
}

int main(int argc, char *argv[]) {

    words1 = malloc(m * sizeof(char*));
    printf("%p\n", words1);
    words2 = malloc(m * sizeof(char*));
    printf("%p\n", words2);

    for (int i=0; i<m; i++) {
        words1[i] = malloc(sizeof(char) * 3);
        words2[i] = malloc(sizeof(char) * 4);
        strcpy(words1[i], "22");
        strcpy(words2[i], "333");
    }

    f(words1);
    f(words2);

    for (int i=0; i<m; i++) {
        free(words1[i]);
        free(words2[i]);
    }
    free(words1);
    free(words2);
}

I have two global **char which I think are on the heap (because malloc).

The signature of f() cannot change, i.e. it can only accept void *.

Importantly, in the real program the data in the **char is too big for the stack.

In short: how do I get the **char back from the *void?


Solution

  • You can simply assign it to the right type back in f():

       char **f_words = v;
        for (int i=0; i<m; i++) {
            printf("%s\n", f_words[i]);
        }
    

    Also, your way of identifying the length of words in f() isn't good.

    You can either pass the length as an additional argument to f() or you could terminate the words list with NULL pointer.