0

I know this question (or similar) was asked many times, but I was still struggling to find a good answer, so please don't mark it as duplicate. I am trying to allocate memory for two arrays of strings. The strings are 500 and 1000 chars long, and the number of strings is known at the runtime. Here is my code:

    char *arrOfPrompts = (char*)calloc(500*maxR, sizeof(char));
    char *arrOfPhonePrompts = (char*)calloc(1000*maxR, sizeof(char));

    char **prompts = (char**)calloc(maxR, sizeof(char*));
    char **phonePrompts = (char**)calloc(maxR,sizeof(char*));

    for (int i = 0; i<maxR; i++)
    {
        prompts[i] = arrOfPrompts+(i*500);
        phonePrompts[i] = arrOfPhonePrompts+(i*1000);
        (prompts[i])[i*500] = '\0';
        (phonePrompts[i])[i*500] = '\0';
    }

..where maxR is number of the arrays. So what I am doing is creating a long char array and then storing strings at 500 offsets. Is this a legit way of doing it? Looks ugly. Also, the reason I put '\0' character at the beginning of every "string" is because I then want to append to it using strcat. Are there any potential problems with this?

Thanks.

2
  • Fair enough about the duplicate, thanks for your help. Commented Aug 22, 2015 at 22:07
  • Neither the casts nor the brackets in (prompts[i])[i*500] add anything useful. Commented Aug 22, 2015 at 22:11

2 Answers 2

3

The following lines are not right. They will end up modifying memory beyond what you have allocated.

    (prompts[i])[i*500] = '\0';
    (phonePrompts[i])[i*500] = '\0';

Let's say maxR is 10.

arrOfPrompts points to an array of 5000 characters.

In the for loop, you use:

prompts[i] = arrOfPrompts+(i*500);

That means prompts[9] points to memory starting at the 4501-th character.

prompt[i][i*500] is prompt[9][4500] for i = 9. That will end up accessing a character that is 4000 elements away from the memory you allocated.

Since you are using calloc to allocate memory, you don't need to do anything more to create empty strings.

If you want to do it anyway, you can use:

    prompts[i][0] = '\0';
    phonePrompts[i][0] = '\0';
Sign up to request clarification or add additional context in comments.

3 Comments

Actually I don't think that I'm ever touching memory beyond allocated one with that code.
Oh, you are absolutely right, took me some time to see it. Thanks! I guess the major drawback of that code is that it's really hard to read.
@IvanInTheHat likewise. totally upticked this.
2

Your code seems fine but it may give unexpected results sometimes. Another method to allocate 2D array of chars is:-

//r=number of rows
//c=number of columns
char **arr = (char **)malloc(r * sizeof(char *));
for (i=0; i<r; i++)
     arr[i] = (char *)malloc(c * sizeof(char));

2 Comments

Happy to see it helps you. :)
@IvanInTheHat "much nicer" - with caveats. It offers a few benefits and a few costs. Super-fragmented memory conditions and row-resizing. I.e. If your memory is so fragmented you can't allocate a contiguous r * 1000 contiguous chars, it can still work with the above code because your taking smaller bites from the apple. The place this can work better is when each row has dynamic length independent of other rows. In that case it is potentially more memory efficient but at the cost of more pointer management. Your code need only free two pointers. With this, you need free r + 1.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.