1

I am new to C and trying to initialise a 2D array. I need both columns of the array to be char *, as they will contain string values.

I have it working with the array storing ints but for some reason, when I try to store string values when it prints it displays (null). Below is the code for how I am initialising and storing the data as an int (This appears to be working).

int **array;
    int row = 0;

    array = malloc(2 * sizeof(int*));
    int i;
    for (i = 0; i < 2; i++)
    {
        array[i] = malloc(2 * sizeof(int));
    }

    array[0][0] = i;
    array[0][1] = i;

    printf("array[0][0]: %i\n", array[0][0]);

Below is how I am doing the above but using string values instead.

char **array;
int row = 0;

array = malloc(2 * sizeof(char*));
int i;
for (i = 0; i < 2; i++)
{
    array[i] = malloc(2 * sizeof(char*));
}

array[0][0] = "Test[0][0]";
array[0][1] = "Test[0][1]";

printf("array[0][0]: %s\n", array[0][0]);

Thanks for any help you can provide.

Boardy
  • 35,417
  • 104
  • 256
  • 447
  • Take a look at [my answer here](http://stackoverflow.com/questions/17033315/correct-way-to-allocate-and-free-arrays-of-pointers-to-arrays/17033507#17033507) and make your life much easier – Dariusz Jun 19 '13 at 09:43
  • It seems that you are mixing up two different concepts, pointer to pointer and 2D array. These are not the same. – Jens Gustedt Jun 19 '13 at 10:08

2 Answers2

3

You have the wrong level of pointer indirection, which is over-complicating things.

I think it would be easier for you if you thought of the array as an array of structures, each structure holding two pointers:

struct row {
  char *column1;
  char *column2;
};

then it's (hopefully) clearer that once you've allocated an array of struct row, you have two pointers in each row, you don't need to allocate room for the pointers themselves.

const size_t num_rows = 1;
struct row * rows = malloc(num_rows * sizeof *rows);
if(rows != NULL)
{
  rows[0].column1 = "row 0, column 1";
  rows[0].column2 = "row 1, column 2";
}

Note that this uses string literals, otherwise you might need to allocate room for the strings to be stored, depending on where the data comes from.

The num_rows value could of course come from anywhere in your program, I'm just trying to illustrate what controls the number of rows memory is allocated for.

unwind
  • 391,730
  • 64
  • 469
  • 606
  • Thanks this seemed to work. The only thing I don't get is what is 1 * sizeof, is the 1 referring to the number of rows that it should contain. So if I had to store 50 rows, would it be ``malloc(50 * sizeof *rows)`` – Boardy Jun 19 '13 at 10:24
  • @Boardy Yes exactly. I'll clarify. – unwind Jun 19 '13 at 13:33
1

Save yourself the trouble and don't use 2D arrays in C. It's more convenient to use 1D arrays.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
    const int nstrings = 2;
    const int width = 20; //width of maximum string.

    char* array = (char*)malloc(sizeof(char)*nstrings*width);
    strcpy(&array[0*width],"Test[0][0]");
    strcpy(&array[1*width],"Test[1][0]");
    printf("string 0: %s\n", &array[0*width]); 
    printf("string 1: %s\n", &array[1*width]);
    free(array);
}
  • 2
    [Don't cast the return value of `malloc()` in C](http://stackoverflow.com/a/605858/28169). And don't use `sizeof (char)`, it adds nothing but clutter. Also, that's pretty ... complicated code, and very different from what the question wanted. – unwind Jun 19 '13 at 10:22
  • 1
    Those are quite pedantic comments. The cast is necessary for it to compile in MSVC as well as C++ (your firm believe in them being separate languages does not have to be my believe). `Sizeof` helps clarify how to do this with other datatypes larger than char. Why break the symmetry for char only (I don't need to write `0*width` either but I think it makes it more clear)? Personally, I think 2D arrays are more complicated so from my point of view my code is less complicated. –  Jun 19 '13 at 10:35