0

I've recently decided to brush up my C knowledge (what little of it I have left). I quite quickly realized that the first skill to go cloudy was memory management. Damned.

I decided that the best thing to do, was to write some pointless pointer exercises. The first one was to allocate an array of 4 char arrays, each of which were of variable length.

A simplified version of that code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
    char **aStr = malloc(4*sizeof(aStr));
    int j = 0;
    int i = 0;
    while(i<sizeof(aStr))
    {
        j = 4 + 2*i;//in my code, length is determined by arguments
        aStr[i] = malloc(j*sizeof(aStr[i]));
        j--;
        strncpy(aStr[i],"RaisinRubarbCarrot"+i,j);
        aStr[i][j] = 0;//just a habbit
        j++;
        printf("ptr@:%p\n\tkey:%d\n\tval:%s\n\tlength:%d (%d)\n\n",*aStr[i],i,aStr[i],j,strlen(aStr[i]));
        i++;
    }
    free(aStr);
    return 0;
}

I felt this to be clunky, and counter-intuitive. Today I remembered my old nemisis: calloc. I then wrote

char **aStr = (char **)calloc(4, sizeof(char *));

and in the loop:

aStr[i] = (char *) calloc(j,sizeof(char *));

I have found code examples that write the last line like so:

aStr[i] = (char *) calloc(j,sizeof(char));//without the asterisk

Question 1: what's the difference, if any?

Question 2: Isn't there another way of allocating an array of strings? the way I see the code now, it feels/looks like I am first allocating 4 pointers to a single char pointer, and then allocating the actual size required for each pointer. That just feels wrong.

Then again I might be wrong about all of this all together, in which case: feel free to bang my head against the wall and point me in the direction of a decent manual I should read before wasting all of your time...

pb2q
  • 58,613
  • 19
  • 146
  • 147
Elias Van Ootegem
  • 74,482
  • 9
  • 111
  • 149

2 Answers2

3

char * and char are two different types, and have different data sizes. A char is always a single byte, so sizeof(char) is always 1. A pointer to char on the other hand, will be 4 bytes on a 32bit system. So if you use sizeof(char*) to allocate space for a string, you'll be allocating much more than you need.

Using the loop to allocate the individual strings is fine. Assuming a maximum length for your strings, you could just allocate one big block, but that would be clumsy.

pb2q
  • 58,613
  • 19
  • 146
  • 147
  • So which of the two methods is to be preferred? `calloc` or `malloc`, because in both cases the code does the same thing. I'm currently using `calloc` because it fits the goal better IMO – Elias Van Ootegem Aug 14 '12 at 05:15
  • `calloc` initializes the data elements to zero for you, and so can prevent certain errors. Otherwise they're equivalent: just use which one you think reads better. But if you use `malloc` be aware that the memory isn't initialized to anything and will be filled with junk data. – pb2q Aug 14 '12 at 05:18
1
  1. You should use sizeof(char) instead of sizeof(char*) because you are trying to allocate memory for an array of chars not an array of poiners to chars. So this is the right version:

    aStr[i] = (char*) calloc(j, sizeof(char)); 
    //first argument number of memory
    //locations to be allocated
    //second argument, size of each location
    

    The difference/advantage of calloc over malloc is that it also initialized the memory locations to 0.

  2. You first allocate an array of 4 pointers to chars. And then, you allocate memory for each of the strings (each of the 4 pointers previously allocated will point to one of these arrays)

Razvan
  • 9,925
  • 6
  • 38
  • 51