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...
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.