How to Dynamically Allocate Arrays in C++

Dynamically allocate an array of strings

Your allocation is not the best, and printf argument arr[i] expects a char* but you pass it an int (a char if you'd like).

Here is how you should do it, with comments:

Live demo

#include <stdio.h>
#include <stdlib.h> //for malloc

int main(){
int n;
int i;

printf("Give me a number:");
scanf("%d", &n);

//declare a variable of pointer to pointer to char
//allocate memory for the array of pointers to char,
//each one capable of pointing to a char array
char **arr = malloc(n * sizeof *arr);

if(arr == NULL){ //check for allocation errors
perror("malloc");
return EXIT_FAILURE;
}

//allocate memory for each individual char array
for(i = 0; i < n; i++){
arr[i] = malloc(40); //char size is always 1 byte

if(arr == NULL){ //check for allocation errors
perror("malloc");
return EXIT_FAILURE;
}
}

for (i = 0; i < n; i++){
printf("Give me a word: ");
//limit the size of read input to 39 charaters to avoid overflow,
//a nul character will be added by scanf
scanf("%39s", arr[i]);
}

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

}

for(int i = 0; i < n; i++){ //free the memory for each char array
free(arr[i]);
}
free(arr); //free array of pointers

return 0;
}

You can also do this with less code using a pointer to array of 40 chars, this will simplify the memory allocation and deallocation:

Sample with comments:

Live demo

#include <stdio.h>
#include <stdlib.h> //for malloc

int main(){
int n;
int i;

printf("Give me a number:");
scanf("%d", &n);

//declare a pointer to array of chars and
//allocate memory for all the char arrays
char (*arr)[40] = malloc(n * sizeof *arr);

if(arr == NULL){ //check for allocation errors
perror("malloc");
return EXIT_FAILURE;
}

for (i = 0; i < n; i++){
printf("Give me a word: ");
scanf("%39s", arr[i]);
}

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

free(arr); //free allocated memory

return 0;
}

Dynamic memory allocation in C for variable length arrays

int x[n];

Automatic storage duration objects including VLAs are (by most modern implementations) allocated on the stack. There are some problems with the larger objects if they are allocated on the stack (three most important ones):

  1. There is no allocation control unless your program fails when you overflow the stack
  2. Stack is usually much much smaller than the heap. So the size of the array is limited
  3. The lifetime of the array is limited to the lifetime of the enclosing block. You can't return the reference to this array on the function return.

Using Dynamic Memory allocation for arrays

You use pointers.

Specifically, you use a pointer to an address, and using a standard c library function calls, you ask the operating system to expand the heap to allow you to store what you need to.

Now, it might refuse, which you will need to handle.

The next question becomes - how do you ask for a 2D array? Well, you ask for an array of pointers, and then expand each pointer.

As an example, consider this:

int i = 0;
char** words;
words = malloc((num_words)*sizeof(char*));

if ( words == NULL )
{
/* we have a problem */
printf("Error: out of memory.\n");
return;
}

for ( i=0; i<num_words; i++ )
{
words[i] = malloc((word_size+1)*sizeof(char));
if ( words[i] == NULL )
{
/* problem */
break;
}
}

if ( i != num_words )
{
/* it didn't allocate */
}

This gets you a two-dimensional array, where each element words[i] can have a different size, determinable at run time, just as the number of words is.

You will need to free() all of the resultant memory by looping over the array when you're done with it:

for ( i = 0; i < num_words; i++ )
{
free(words[i]);
}

free(words);

If you don't, you'll create a memory leak.

You could also use calloc. The difference is in calling convention and effect - calloc initialises all the memory to 0 whereas malloc does not.

If you need to resize at runtime, use realloc.

  • Malloc
  • Calloc
  • Realloc
  • Free

Also, important, watch out for the word_size+1 that I have used. Strings in C are zero-terminated and this takes an extra character which you need to account for. To ensure I remember this, I usually set the size of the variable word_size to whatever the size of the word should be (the length of the string as I expect) and explicitly leave the +1 in the malloc for the zero. Then I know that the allocated buffer can take a string of word_size characters. Not doing this is also fine - I just do it because I like to explicitly account for the zero in an obvious way.

There is also a downside to this approach - I've explicitly seen this as a shipped bug recently. Notice I wrote (word_size+1)*sizeof(type) - imagine however that I had written word_size*sizeof(type)+1. For sizeof(type)=1 these are the same thing but Windows uses wchar_t very frequently - and in this case you'll reserve one byte for your last zero rather than two - and they are zero-terminated elements of type type, not single zero bytes. This means you'll overrun on read and write.  

Addendum: do it whichever way you like, just watch out for those zero terminators if you're going to pass the buffer to something that relies on them.

How can i create dynamically allocated array In C

Assuming you have the number of rows "r" and the number of columns "c", you can do this:

int **arr;
arr = malloc(r*sizeof(int*));
for(int i=0; i < r; i++)
{
arr[i] = malloc(c*sizeof(int));
}

this dynamically allocates an array of pointers to integers, and then allocates arrays of integers to each pointer. Don't forget to delete dynamically allocated arrays when you're done, in this case you should delete the integer arrays first and then the pointer array:

for(int i=0; i < r; i++)
{
free(arr[i]);
}
free(arr);

dynamic allocating array of arrays in C

The m[line][column] = 12 syntax is ok (provided line and column are in range).

However, you didn't write the code you use to allocate it, so it's hard to get whether it is wrong or right. It should be something along the lines of

m = (int**)malloc(nlines * sizeof(int*));

for(i = 0; i < nlines; i++)
m[i] = (int*)malloc(ncolumns * sizeof(int));

Some side-notes:

  • This way, you can allocate each line with a different length (eg. a triangular array)
  • You can realloc() or free() an individual line later while using the array
  • You must free() every line, when you free() the entire array


Related Topics



Leave a reply



Submit