-1

I learnt to create heap allocation of 2-D char array and initialize it.

Method 1:

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

int main()
{
    char ** arr;
    arr = (char **) malloc(2 * sizeof(char *));
    arr[0] = (char *) malloc(256 * sizeof(char));
    arr[1] = (char *) malloc(256 * sizeof(char));

    sprintf(arr[0], "%s", "This is string 1");
    sprintf(arr[1], "%s", "This is string 2");

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

    return 0;
}

But I'm trying to learn is to pass the pointer to a function to create a 2-D array, but in vain.

Method 2:

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

void test(char *** ptr);

int main()
{
    char ** arr;
    test(&arr);

    sprintf(arr[0], "%s", "This is string 1");
    sprintf(arr[1], "%s", "This is string 2");

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

    return 0;
}

void test(char *** ptr)
{
    **ptr = (char **) calloc(2, sizeof(char *));
    *ptr[0] = (char *) malloc(256 * sizeof(char));
    *ptr[1] = (char *) malloc(256 * sizeof(char));
}

Something wrong with the way I'm doing it in Method 2. Please help me understand the way of doing heap allocation of 2-D array by passing pointers. Thanks.

r18ul
  • 1,082
  • 2
  • 12
  • 30
  • None of your code snippets uses a 2D array, contains something that can represent ore point to one! A pointer is not an array! Whoever told you different is plain wrong. If you need a 2D array, use one! – too honest for this site Sep 09 '16 at 18:42

3 Answers3

3

On the first allocation you're not using the proper level of indirection. You want *ptr, not **ptr.

For the second and third allocations, operator precedence is getting you. The array index operator [] has higher precedence than the dereference operator * so you need parenthesis to first dereference, then index the array:

void test(char *** ptr)
{
    *ptr = calloc(2, sizeof(char *));
    (*ptr)[0] = malloc(256 * sizeof(char));
    (*ptr)[1] = malloc(256 * sizeof(char));
}

Rather than using a triple pointer (which as you found out can be confusing), return the allocated value instead and assign that to your variable:

char **test()
{
    char **ptr = calloc(2, sizeof(char *));
    ptr[0] = malloc(256 * sizeof(char));
    ptr[1] = malloc(256 * sizeof(char));
    return ptr;
}

...

arr = test();

Note that this is much cleaner.

Also, don't cast the return value of malloc/calloc/realloc.

Community
  • 1
  • 1
dbush
  • 205,898
  • 23
  • 218
  • 273
  • So you are a 3-star C-programmer, too?;-) Any reason your `void` function does not just return the not-a-2D-array array? (And why not use 2 2D array?) – too honest for this site Sep 09 '16 at 18:43
  • Can someone help me learn the nuances of passing pointers as function arguments? Please direct me to some tutorials or learning resources to master this 3-star programming concept. Thanks. – r18ul Sep 09 '16 at 18:55
  • 1
    @Rahul Recommending references is off-topic for this site. Besides, the "3 star programmer" concept means you're making code more complicated than it needs to be. The second example in the answer is more concise, easier to read, and doesn't depend on parenthesis for things to works correctly. – dbush Sep 09 '16 at 19:04
0

Due to operator precedence the expression *ptr[0] is parsed as *(ptr[0]) which is not really correct.

You need to use explicit parentheses to overcome it as in (*ptr)[0].


As an unrelated side-note, being called a three star programmer is usually not a compliment.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • But the warning message is at the line in the test(char *** ptr): **ptr = (char **) calloc(2, sizeof(char *)); – r18ul Sep 09 '16 at 18:30
0

A note:

*ptr[0] == *(ptr[0]) == **ptr

therefore

*ptr[1] == *(ptr[1]) == *(*(ptr+1)) == unknown memory

Fixed code:

void test(char *** ptr)
{
    *ptr      = (char** ) calloc(2, sizeof(char *));
    (*ptr)[0] = (char*  ) malloc(256 * sizeof(char));
    (*ptr)[1] = (char*  ) malloc(256 * sizeof(char));
}

Explanation: Explanation Image

W2a
  • 736
  • 2
  • 9
  • 23