Good day. I have this: MAP_ITEM **map what I think is pointer to array of pointers (correct me if I am wrong please) and I have to allocate space for it. I can allocate space using malloc for 1 pointer, but have no idea how to do this. help would be really appreciated.
Here is an example, written for use with char **, but you can modify for your purposes:
char ** allocMemory(char ** a, int numStrings, int maxStrLen)
{
int i;
a = calloc(sizeof(char*)*(numStrings+1), sizeof(char*));
for(i=0;i<numStrings; i++)
{
a[i] = calloc(sizeof(char)*maxStrLen + 1, sizeof(char));
}
return a;
}
call it like this: (for array of 10 strings, each having maximum of 79 characters (leave one for NULL term)
char **arrayOfString;
arrayOfString = allocMemory(arrayOfString, 10, 80);
//
You also need to free memory created with allocMemory
void freeMemory(char ** a, int numStrings)
{
int i;
for(i=0;i<numStrings; i++)
if(a[i]) free(a[i]);
free(a);
}
Call it like this:
freeMemory(arrayOfStrings, 10);
Import the stdlib.h
Then use the malloc function.
Where is an example for a one dimentional array:
int* my_in_array = (int*) malloc(sizeof(int) * size_of_my_array);
Note that malloc receives the number of bytes you want to allocate, so sizeof will tell you how many bytes a datatype will need (in this case an int, but it can be used for chars, structures, ...) and then I multiplicate it by size_of_my_array, wich is the number of elements of my array.
Now, just try to se this for you case.
Related
I'm reading about dynamic memory allocation for 2D arrays, and I'm looking at this example:
int nrows = 2;
int ncols = 5;
char **pvowels = malloc(nrows * sizeof(char));
pvowels[0] = malloc(ncols * sizeof(char));
pvowels[1] = malloc(ncols * sizeof(char));
My understanding is that the 2nd and 3rd malloc both allocate memory the size of 5 chars and pvowels[0] and pvowels[1] point to each, but I'm having trouble understanding the first malloc.
The first malloc looks like it allocates memory the size of 2 chars, and uses it to store the two pointers. But isn't a char only 256 possible values, and pointers can go up to billions? So if it's allocating memory for storing pointers, doesn't it need to be bigger than chars?
Firstly, your first malloc() is incorrect. Using nrows * sizeof(char) only allocates 2 bytes, whereas you need 2 rows of char* pointers. You have to allocate like this instead:
char **pvowels = malloc(nrows * sizeof(char*));
Or:
char **pvowels = malloc(nrows * sizeof(*pvowels));
Also note that char **pvowels is not a 2D array, but simply a pointer to a char pointer. If you were using a 2D array, such as char pvowels[][], you wouldn't need to dynamically allocate pointers on the heap. You could also just use a 2D array for your problem, such as char pvowels[2][5], as ncols and nrows seems to be fixed in this case.
Secondly, your allocations for pvowels[0] and pvowels[1] will only make space for 4 valid characters, such as "abcd", because 1 space is needed for the null terminating character \0. You should write instead:
pvowels[0] = malloc(ncols+1); /* +1 for '\0' */
pvowels[1] = malloc(ncols+1);
Note: sizeof(char) is always 1, so their is no need to include it. You should also check that malloc() returned NULL or not.
Allocating for an array of nrows pointers to char, and then separately allocating for nrows arrays of ncols chars has a disadvantage, in that the separate memory allocations are not guaranteed to be contiguous in memory. This fragmentation can lead to performance penalties.
A better approach is to allocate enough memory to hold a 2d array, and assign the resulting pointer to a pointer to an array of ncols chars. As shown here, this approach does rely on VLA's, but these have been a part of C since C99. This has the advantage of allocating memory at once, with only one allocation to free.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
size_t nrows = 2;
size_t ncols = 5;
/* Allocate space for a 2d array */
char (*pvowels)[ncols] = malloc(sizeof (char[nrows][ncols]));
/* Another alternative */
// char (*pvowels)[ncols] = malloc(nrows * ncols);
if (pvowels == NULL) {
fprintf(stderr, "Unable to allocate memory\n");
exit(EXIT_FAILURE);
}
for (size_t i = 0; i < nrows; i++) {
for (size_t j = 0; j < ncols; j++) {
pvowels[i][j] = 'a' + i * ncols + j;
}
}
for (size_t i = 0; i < nrows; i++) {
for (size_t j = 0; j < ncols; j++) {
printf("%5c", pvowels[i][j]);
}
putchar('\n');
}
free(pvowels);
return 0;
}
Program output:
a b c d e
f g h i j
char **pvowels is a pointer to a pointer, meaning it behaves like an array declared like this:
char * pvowels[a number];
So basically, pointers to chars, and not pointers are being assigned in the example you provided.
A simple and easy to understand code:(Using just a single pointer to store and access)
#include<stdio.h>
#include<stdlib.h>
int main(){
int *a,n,r,c,i,j;
scanf("%d",&n);
r=c=n;
a=(int *)malloc(r*c*sizeof(int));
for(i=0;i<r;i++)
{
for(j=0;j<c;j++){
scanf("%d",(a+i*c+j));
}
}
for(i=0;i<r;i++)
{
for(j=0;j<c;j++){
printf("%d",*(a+i*c+j));
}
}
}
References: geeksforgeeks.org
Is it possible to declare a 2D array in C, then set its size later on? I know in C you have to deal with memory and such, but I cannot find answer to this question despite all my searching.
My current example is..
int boardsize, linewin;
char array[1][1];
//boardsize is set within here.
array = [boardsize][boardsize];
With C you will need to do your own dynamic array management using pointers.
See the following articles on how to go about doing so using an allocated memory area.
Malloc a 2D array in C
Using malloc for allocation of multi-dimensional arrays with different row lengths
Since you are looking to modify these, you may also need to use the realloc() function or the free() function to release allocated memory.
For information about using the realloc() function look at the following stack overflow.
Realloc double 2D array in C
two-dimensional dynamic array (realloc in c)
EDIT - Adding an example
Here are two functions to malloc() a two dimensional array and to realloc() a two dimensional array. You could actually just use the realloc() version if you pass a NULL pointer to realloc2dCArray() for the memory area to be reallocated.
What I have tried to do is to use a single malloc() and realloc() for all of the memory needed so that you can free() the memory with a single call to free().
char **malloc2dCArray (int nRows, int nCols)
{
// use a single malloc for the char pointers to the first char of each row
// so we allocate space for the pointers and then space for the actual rows.
char **pArray = malloc (sizeof(char *) * nRows + sizeof(char) * nCols * nRows);
if (pArray) {
// calculate offset to the beginning of the actual data space
char *pOffset = (char *)(pArray + nRows);
int i;
// fix up the pointers to the individual rows
for (i = 0; i < nRows; i++) {
pArray[i] = pOffset;
pOffset += nCols;
}
}
return pArray;
}
char **realloc2dCArray (char **pOld, int nRows, int nCols)
{
// use a single realloc for the char pointers to the first char of each row
// so we reallocate space for the pointers and then space for the actual rows.
char **pArray = realloc (pOld, sizeof(char *) * nRows + sizeof(char) * nCols * nRows);
if (pArray) {
// calculate offset to the beginning of the actual data space
char *pOffset = (char *)(pArray + nRows);
int i;
// fix up the pointers to the individual rows
for (i = 0; i < nRows; i++) {
pArray[i] = pOffset;
pOffset += nCols;
}
}
return pArray;
}
To use these functions you would do something like the following:
char **pChars = malloc2dCArray (16, 8);
int i, j;
for (i = 0; i < 16; i++) {
for (j = 0; j < 8; j++) {
pChars[i][j] = 0;
}
}
To do a realloc() you will want to check that the realloc() worked so use a temporary variable and check for NULL before using it.
{
char **pChars2 = realloc2dCArray (pChars, 25, 8);
if (pChars2) pChars = pChars2;
}
You could also just use the realloc() version if you provide a NULL pointer since realloc() will do a malloc() if the pointer to the memory to realloc() is NULL.
I did some testing of this using a debugger and it looks like it is working to me.
I'm getting a segmentation fault when I loop through this 2-d pointer array
declaration:
char **addr;
addr=malloc((y)*sizeof(char)); //y is 3
for(i=0;i<y;i++)
{
*(addr+i)=malloc(x*sizeof(char)); //x is 100
}
independent access works:
*(*(addr+2)+0)='a';
printf("%c\n",*(*(addr+2)+0));
loop returns a segmentation fault at addr[2][0] regardless of what y and x are
for(j=0;j<x;j++)
{
for(i=0;i<y;i++)
{
printf("%d %d\n",j,i);
*(*(addr+j)+i)='a';
}
}
addr=malloc((y)*sizeof(char));
must be replaced by
addr = malloc(y * sizeof(char *));
Try using the X *x = malloc(sizeof *x) idiom when allocating memory :
addr = malloc(y * sizeof *addr);
So the result of sizeof actually refers to the type of the data you're pointing to :
sizeof *addr == sizeof(char *)
The previous answers are good. This is just an alternative you may consider. It is a way to do what you are doing, that also will help to free the memory properly (which is sometimes a pain with multi-pointer arrays)
Define functions to do the work:
char ** allocMemory(char ** a, int numStrings, int maxStrLen)
{
int i;
a = calloc(sizeof(char*)*(numStrings+1), sizeof(char*));
for(i=0;i<numStrings; i++)
{
a[i] = calloc(sizeof(char)*maxStrLen+ 1, sizeof(char));
}
return a;
}
void freeMemory(char ** a, int numStrings)
{
int i;
for(i=0;i<numStrings; i++)
if(a[i]) free(a[i]);
free(a);
}
Then you can simply call these functions with parameters you have created for any number of strings, with a max string length, then free the same with a pre-configured function.
So your code would look like this:
char **addr;
addr = allocMemory(addr, 100, 3); //100 strings of max length == 3
Then, when you are done with addr:
freeMemory(addr, 100); //free 100 strings, and associated pointers.
Is there any way to assign all elements of an array the value 0 in one go.The array accepts its size from the user. Hence
int array[x] = {0};
Won't work!
int *array;
int i;
printf ("Amount of numbers to be entered: ");
scanf ("%d",&i);
array = (int*) calloc (i,sizeof(int));
You will need to dynamically allocate the memory for this array:
int *array;
int x;
scanf("%d\n", &x);
array = malloc(sizeof(int) * x);
then set value for all of them
memset(array, 0, x);
or use calloc:
array = calloc(x, sizeof(int));
Use memset
void * memset ( void * ptr, int value, size_t num );
int *array = (int *) malloc(sizeof(int) * x);
memset(array,0,sizeof(int) * x);
OR Use:
void* calloc (size_t num, size_t size);
int *array = (int *) calloc(x, sizeof(int));
My best bet is to use memset from string.h library.
memset(array,0,x*sizeof(int));
This is not technically initialization, because there is no assignment, it only sets all bytes in given memory to '0' but that's exactly what you want to do here.
Also, consider using malloc for creating your array, because the way you do it now, your array will be created on the stack(which has finite capacity) and will be freed when function that creates it returns(just like regular automatic variable). That means your array is inaccessible from outside of its local scope.
After using this function to allocate a 2-d array:
char** make_matrix(int M, int N)
{
char** MAT = (char**)malloc(M * sizeof(char));
for (int i = 0; i < M; i++)
{
MAT[i] = (char*)malloc(N * sizeof(char));
}
return MAT;
}
I found that trying to free(M[0]) causes an assertion failure. All that I can find relating to freeing 2-d arrays use int instead of char. Yet replace every char with int above and the assertion failure disappears. Why is this, and how can I then free the entire 2-d array?
You are allocating too little memory for MAT. Change relevant line to:
char** MAT = (char**)malloc(M * sizeof(char*));
This is because MAT is array of pointers, not characters. Since your code did not allocate enough memory, it was likely writing outside of array bounds and corrupting memory.
It could work with integers because they are bigger, so with some luck you could have been allocating just enough memory (at least on 32 bit machine).
The first malloc call is M * sizeof(char) instead of sizeof(char *). The sizeof(char) would be 1 byte, the size of a char* is likely 4 bytes.
Edit: I see someone beat me to the punch. Accept the other guy's answer.
You should iterate through all the rows of the matrixes and free them first, and then finally the MAT
something like this:
void free_matrix(int M)
{
for (in i = 0; i < M; i++)
{
free(MAT[i]);
}
free(MAT);
}
To release the space (assuming it is correctly allocated), you need a call to free() corresponding to each call to malloc().
void destroy_matrix(char **MAT, int M)
{
for (int i = 0; i < M; i++)
free(MAT[i]);
free(MAT);
}
Your code works when you replace char with int because sizeof(int) == sizeof(int *) on your (32-bit) system. It's largely by coincidence; you'd be in trouble again on a 64-bit system.