Dynamic array in C - how to make it work? - c

I'm trying to make function for dynamic arrays in C but I'm not sure, if I'm solving it right way. Could you help me?
Here is my code:
int resizeArray(int array_rows, int **array[])
{
int new_rows = array_rows + 16;
int *pointer;
pointer = realloc(**array, new_rows*sizeof(int));
if (!pointer) {
free(**array);
return 0;
}
**array = pointer;
free(pointer);
return new_rows; // return new rows counter
};
some code....
/* first array definition */
int *data;
int array_rows = 16;
data = (int*)malloc(array_rows*sizeof(int));
if array is full:
array_rows = resizeArray(array_rows,&data);
Thank you very much for your reviews and tips.
EDIT:
int resizeArray(int array_rows, int **array){
int new_rows = array_rows + 16;
int *pointer;
pointer = realloc(**array, new_rows*sizeof(*pointer));
if (!pointer) {
free(**array);
return 0;
}
**array = pointer;
free(pointer);
return new_rows; // return new rows counter
}
some code....
/* first array use */
int *data;
int array_rows = 16;
data = (int*)malloc(array_rows*sizeof(*data));
if array is full:
array_rows = resizeArray(array_rows,&data);
EDIT - CODE WITH STRUCTURES:
struct MyDynamicArray {
int maximumSize = 16;
int length = 0;
int* data;
}
/* first array definition */
MyDynamicArray.data = (int*)malloc(MyDynamicArray.maximumSize*sizeof(int));
int resizeArray(int array_rows, struct MyDynamicArray)
{
int new_rows = MyDynamicArray.maxSize * 2;
int *pointer;
pointer = realloc(MyDynamicArray.data, new_rows*sizeof(int));
if (!pointer) {
free(MyDynamicArray.data);
return 0;
}
MyDynamicArray.maxSize = new_rows; // return new rows counter
};
/* usage */
resizeArray(array_rows,MyDynamicArray);
WORKING SOLUTION:
resizeArray function definition:
/**
* resize array
* - its size resize X 2
* #param max_length
* #param data
* #return
*/
int resizeArray(int max_length, int **data)
{
data = (int *) realloc(**data, max_length * 2 * sizeof(int));
max_length *= 2;
return max_length; // return new rows counter
}
FIRST ARRAY DEFINITION
int *data_i;
int max_length = 16;
int *data;
data = (int *) realloc((void *) data_i, max_length * sizeof(int));
HERE IS USAGE:
int i = 0;
for(i = 0; i < 100; i++)
{
data[i] = i;
if(i == max_length)
{
max_length = resizeArray(max_length, &data);
}
}
I hope, it's right and will help to solve someones problem.

A few things:
It very well may work, but you have pointers going crazy. The second parameter can simply be int* array (and when you call it, there is no need to reference it). This way, the call to realloc will simply take array, as will the calls to free. (and you simply have array = pointer;
You're freeing the newly allocated memory. This will cause a segfault if you try to use the array after resizing. Remove that line, memory management should be the responsibility of function.
Also, in general, dynamic arrays will resize by doubling their size. realloc is expensive, but memory these days is cheap. This noted, it may be beneficial for you to always call resizeArray whenever you write to it, and pass it the length of the array plus the amount of elements you are writing. I'm not certain what you are going to do with your new, dynamic array, but it will likely save you many headaches if you maintain something like:
struct MyDynamicArray {
int maximumSize;
int length;
int* data;
}

There are so many iterations of MyDynamicArray it's hard to discern the final approach taken. One area where there seems to be confusion is over what am I reallocating?. Here, it appears you simply have one MyDynamicArray struct and an int array data member of that struct then needs reallocating. There are a number of approaches to doing this, but a clean approach is to #define an initial array size, allocate your data array to the initial defined size, then when the number of elements reaches initial size - 1 reallocate data.
An example taking the approach is as follows. A typedef to the struct has been created to cut down on typing. Look though the code, understand what it is doing where, and drop a comment if you have additional questions:
#include <stdio.h>
#include <stdlib.h>
#define ARRSZ 5
typedef struct
{
size_t size;
int* data;
} MyDynamicArray;
int *resizeArray (int **mdata, size_t newsize)
{
int *tmp = realloc (*mdata, newsize * sizeof(int));
if (!tmp)
return NULL;
*mdata = tmp;
return *mdata;
}
int main () {
MyDynamicArray *mda = malloc (sizeof (MyDynamicArray));
mda->size = ARRSZ;
mda->data = malloc (ARRSZ * sizeof (int));
int i = 0;
int newsize = 0;
for (i = 0; i < 50; i++)
{
if (i >= mda->size - 1)
{
newsize = 2 * mda->size;
if (resizeArray (&mda->data, newsize))
mda->size = newsize;
else {
fprintf (stderr, "error: reallocation failed at mda->size: %zd\n", mda->size);
exit (EXIT_FAILURE);
}
}
mda->data[i] = i;
}
printf ("\nElements of dynamic array:\n\n");
for (i = 0; i < 50; i++)
printf (" mda->data[%2d] : %d\n", i, mda->data[i]);
if (mda->data) free (mda->data);
if (mda) free (mda);
return 0;
}
Note: you can also assign a newpointer when you realloc if for some reason that is desirable. (e.g. int *newptr = resizeArray (&mda->data, newsize);) However, for simply resizing your array resizeArray (&mda->data, newsize); is sufficient.
output:
$ ./bin/mydynarray
Elements of dynamic array:
mda->data[ 0] : 0
mda->data[ 1] : 1
mda->data[ 2] : 2
mda->data[ 3] : 3
mda->data[ 4] : 4
mda->data[ 5] : 5
mda->data[ 6] : 6
mda->data[ 7] : 7
mda->data[ 8] : 8
mda->data[ 9] : 9
mda->data[10] : 10
mda->data[11] : 11
mda->data[12] : 12
mda->data[13] : 13
mda->data[14] : 14
mda->data[15] : 15
mda->data[16] : 16
mda->data[17] : 17
mda->data[18] : 18
mda->data[19] : 19
mda->data[20] : 20
mda->data[21] : 21
mda->data[22] : 22
mda->data[23] : 23
mda->data[24] : 24
mda->data[25] : 25
mda->data[26] : 26
mda->data[27] : 27
mda->data[28] : 28
mda->data[29] : 29
mda->data[30] : 30
mda->data[31] : 31
mda->data[32] : 32
mda->data[33] : 33
mda->data[34] : 34
mda->data[35] : 35
mda->data[36] : 36
mda->data[37] : 37
mda->data[38] : 38
mda->data[39] : 39
mda->data[40] : 40
mda->data[41] : 41
mda->data[42] : 42
mda->data[43] : 43
mda->data[44] : 44
mda->data[45] : 45
mda->data[46] : 46
mda->data[47] : 47
mda->data[48] : 48
mda->data[49] : 49

Related

Structure variable has Pointer variable in c

I want to know why structure variable passes pointer variable to create memory.
what happens if we do box *boxes = malloc(n * sizeof(box));
Then we pass address to scanf function. Pointer actually stores the address. Then why we pass "&" of scanf to pointer ?
for (int i = 0; i < n; i++) {
scanf("%d%d%d", &boxes[i].length, &boxes[i].width, &boxes[i].height);
}
#include <stdio.h>
#include <stdlib.h>
#define MAX_HEIGHT 41
struct box
{
/**
* Define three fields of type int: length, width and height
*/
int length,width,height;
};
typedef struct box box;
int get_volume(box b) {
/**
* Return the volume of the box
*/
return b.length*b.width*b.height;
}
int is_lower_than_max_height(box b) {
/**
* Return 1 if the box's height is lower than MAX_HEIGHT and 0 otherwise
*/
return b.height < 41 ? 1 : 0;
}
int main()
{
int n;
scanf("%d", &n);
box *boxes = malloc(n * sizeof(box));
for (int i = 0; i < n; i++) {
scanf("%d%d%d", &boxes[i].length, &boxes[i].width, &boxes[i].height);
}
for (int i = 0; i < n; i++) {
if (is_lower_than_max_height(boxes[i])) {
printf("%d\n", get_volume(boxes[i]));
}
}
return 0;
}
When I tried running the sizeof struct,I got the sizeof Struct box it was 12.
Say n = 5, Then what will be the memory space?
memory = 12 * 5 ?
malloc() is used to allocate dynamic and variable sized memory. So we use this to create an array of n structures.
You need & because scanf() needs the address of the variable to store the input data to. b is a pointer, but b[i].length is just an ordinary structure member accessed by dereferencing that pointer. You need to get its address to pass to scanf().
box *boxes = malloc(n * sizeof(box));
Allocates enough space for n instances of box on the heap and returns a pointer to it
scanf("%d%d%d", &boxes[i].length///
is passing the address of boxes[i].length to scanf. Scanf needs to write there so its needs the address. Its just like
scanf("%d", &n);
that you did earlier
sizeof(struct box)
equaling 12 is fine. It has 3, 4 byte integers. You wont always get it that simply , the compiler might pad the structure to align things on 2, 4 or 8 byte boundaries, this is why sizeof exists
Say n = 5, Then what will be the memory space? memory = 12 * 5 ?
yes

Structure's int field gets modified after malloc() on the same structure's int*

#define MAX_NUM_STACKS_ALLOWED 10
#define MAX_PLATES_PER_STACK 5
#define NEW_STACKS_CREATION_INC 2
typedef struct stackOfPlates {
int currentStackIndex;
int currentStackTop[MAX_NUM_STACKS_ALLOWED];
int currentMaxStacks;
int **stackOfPlatesArray;
} stackOfPlates_t;
stackOfPlates_t *stackOfPlates_Init(void) {
stackOfPlates_t *stackOfPlates = (stackOfPlates_t *)malloc(sizeof(stackOfPlates));
stackOfPlates->stackOfPlatesArray = (int **)malloc(NEW_STACKS_CREATION_INC * sizeof(int *));
stackOfPlates->currentStackIndex = 0;
stackOfPlates->currentMaxStacks = NEW_STACKS_CREATION_INC;
int i;
for (i = 0; i < stackOfPlates->currentMaxStacks; i++) {
stackOfPlates->stackOfPlatesArray[i] = (int *)malloc(MAX_PLATES_PER_STACK * sizeof(int));
printf("%d\n", stackOfPlates->currentMaxStacks);
}
for (i = 0; i < MAX_NUM_STACKS_ALLOWED; i++) {
stackOfPlates->currentStackTop[i] = -1;
}
return stackOfPlates;
}
void main()
{
stackOfPlates_t *stackOfPlatesA;
stackOfPlatesA = stackOfPlates_Init();
}
The output of the above code is:
2 (expected),
0 (not expected, not sure how this field gets modified)
I'm trying to malloc the 2D array (stackOfPlates->stackOfPlatesArray). After allocating memory for the NEW_STACKS_CREATION_INC number of stacks, I allocate memory for MAX_PLATES_PER_STACK for every stack. During this operation, I find that my stackOfPlates->currentMaxStacks gets modified to 0.
Could someone please explain why?
In your code
malloc(sizeof(stackOfPlates));
should be
malloc(sizeof(*stackOfPlates));
As you want to allocate memory for the structure type not the pointer to structure type.
That said, see this: Do I cast the result of malloc?

Remove element from dynamic array of structure

I'm working in C
I have a struct called Entity and I create a dynamic array of that struct. Then I try to remove one element from the array but I don't get the behaviour I want.
Here is the code I'm using:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Entity
{
int x, y;
int velX, velY;
}Entity;
int remove_element(Entity** array, int sizeOfArray, int indexToRemove)
{
int i;
printf("Beginning processing. Array is currently: ");
for (i = 0; i < sizeOfArray; ++i)
printf("%d ", (*array)[i].x);
printf("\n");
Entity* temp = malloc((sizeOfArray - 1) * sizeof(Entity)); // allocate an array with a size 1 less than the current one
memmove(
temp,
*array,
(indexToRemove+1)*sizeof(Entity)); // copy everything BEFORE the index
memmove(
temp+indexToRemove,
(*array)+(indexToRemove+1),
(sizeOfArray - indexToRemove)*sizeof(Entity)); // copy everything AFTER the index
printf("Processing done. Array is currently: ");
for (i = 0; i < sizeOfArray - 1; ++i)
printf("%d ", (temp)[i].x);
printf("\n");
free (*array);
*array = temp;
return 0;
}
int main()
{
int i;
int howMany = 20;
Entity* test = malloc(howMany * sizeof(Entity*));
for (i = 0; i < howMany; ++i)
(test[i].x) = i;
remove_element(&test, howMany, 14);
--howMany;
return 0;
}
And the output I get :
Beginning processing. Array is currently: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
Processing done. Array is currently: 0 1 2 3 4 1866386284 6 7 8 9 10 11 12 13 15 16 17 18 19
Then the program crashes at the free (*array); line.
I want my second line to be 0 1 2 3 4 5 6 7 8 9 10 11 12 13 15 16 17 18 19.
How could I solve my problem ?
First thing you have allocated memory space for holding 20 Enity*. Then you have dereferenced it (and the value it contained is indeterminate). This is undefined behavior. And all story ends here.
But let's analyze what you mostly wanted.
Entity* test = malloc(howMany * sizeof(Entity));
^^^^^^^
is what you wanted. Because only if you do this you will get the member elements x and so on.
Also if you are considering 0 indexing then the memmove calls should be
memmove(temp, *array, (indexToRemove)*sizeof(Entity));
memmove(temp+indexToRemove, (*array)+(indexToRemove+1),
(sizeOfArray - indexToRemove - 1)*sizeof(Entity));
These two changes will be enough to solve the problems you are facing and realizing the correct behavior. (If this is all there is in your code).
Also as per standard the main() should be declared like this in case it doesn't take any parameter int main(void). Free the dynamically allocated memory when you are done working with it. Also you should check the return value of malloc - in case it fails it returns NULL and you should handle that case.
Your offset calculations are off by one in both memmove instances. Use this instead:
// copy everything BEFORE the index
memmove(temp,
*array,
indexToRemove * sizeof(Entity));
// copy everything AFTER the index
memmove(temp + indexToRemove,
*array + indexToRemove + 1,
(sizeOfArray - indexToRemove - 1) * sizeof(Entity));
In main itself your memeory allocation is not done properly.if you are using double pointer you should allocate memory first for double pointer and than single pointer in loop one by one.
a little touch
remove element in any type of struct array
regards
int remove_element(void **input_ptr, int input_size, int index_remove, int struct_size)
{
void *temp_ptr;
temp_ptr = malloc((input_size - 1) * struct_size);
if (temp_ptr == 0)
return -1;
memmove(temp_ptr, *input_ptr, index_remove * struct_size);
memmove(temp_ptr + (index_remove * struct_size), (*input_ptr) + (index_remove + 1) * struct_size, (input_size - index_remove - 1) * struct_size);
free(*input_ptr);
*input_ptr = temp_ptr;
return 1;
}
usage example for question struct
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Entity
{
int x, y;
int velX, velY;
}Entity;
int remove_element(void **input_ptr, int input_size, int index_remove, int struct_size)
{
void *temp_ptr;
temp_ptr = malloc((input_size - 1) * struct_size);
if (temp_ptr == 0)
return -1;
memmove(temp_ptr, *input_ptr, index_remove * struct_size);
memmove(temp_ptr + (index_remove * struct_size), (*input_ptr) + (index_remove + 1) * struct_size, (input_size - index_remove - 1) * struct_size);
free(*input_ptr);
*input_ptr = temp_ptr;
return 1;
}
int main()
{
int i;
int howMany = 20;
Entity* test = malloc(howMany * sizeof(Entity));
for (i = 0; i < howMany; ++i)
{
(test[i].x) = i;
printf("test[%d].x = '%d'\n", i, test[i].x);
}
remove_element((void**)&test, howMany, 14, sizeof(Entity));
--howMany;
printf("Deleted index --- new array\n");
for (i = 0; i < howMany; ++i)
printf("test[%d].x = '%d'\n", i, test[i].x);
return 0;
}

Memory allocation to struct in pure C

I have a structure , which present my element of data
struct myElement
{
int field1;
int field2;
int field3;
};
another structure, which contain array of this elements and some another data
struct myArray
{
struct myElement *elements;
int someData;
};
and I need to have array of this arrays like that
struct myArray *myMatrix;
But I have a problem with memory allocation. Count of elements in myArray's can be different, in myMatrix too, so I need to allocate memory dynamicaly. What is the corret way to allocate and deallocate memory in this situation?
Here's a small example of how you would allocate (malloc) and deallocate (free) a dynamic struct myElement array in a struct myArray. Note also that you will need to keep track of the size of the array, so I added size_t elements_len; to struct myArray (excuse the combination of camelCase and underscores - I use underscores in C, but didn't want to modify your identifiers):
#include <stdlib.h>
struct myElement
{
int field1;
int field2;
int field3;
};
struct myArray
{
struct myElement *elements;
size_t elements_len;
int someData;
};
void allocate_elements(struct myArray *m, size_t length)
{
m->elements = malloc(length * sizeof( *m->elements) );
m->elements_len = length;
}
void free_elements(struct myArray *m)
{
free(m->elements);
m->elements = NULL; /* point to NULL to signify no array allocated */
m->elements_len = 0; /* length of 0 also signifies no elements/no array */
}
int main(void)
{
struct myArray ma;
allocate_elements(&ma, 5);
free_elements(&ma);
return 0;
}
Apply similar logic in order to have a dynamic array of struct myArray. You would malloc enough memory for X amount of struct myArrays, then for each struct myArray element in that array, you would call allocate_elements. Then iterate through each element in the array once you're done with it and call free_elements.
Use malloc to allocate the memory:
myMatrix = malloc(sizeof(myArray)*dim1);
for (int i = 0; i < dim1; i++)
myMatrix[i].elements = malloc(sizeof(myElement)*dim2);
Use free in similar fashion to release the memory once you're done with it.
struct myArray *myMatrix = malloc(Nentries * sizeof(*myMatrix));
if (myMatrix != 0)
{
for (int i = 0; i < Nentries; i++)
{
myMatrix[i].elements = malloc(Nelements[i] * sizeof(myElement));
if (myMatrix[i].elements != 0)
{
for (int j = 0; j < Nelements[i]; j++)
{
myElement *e = &myMatrix[i].elements[j];
e->field1 = 0;
e->field2 = 1;
e->field3 = 2;
}
myMatrix[i].someData = 37;
}
}
}
I'm assuming that Nentries says how many elements there are in the matrix, and that each element of the array Nelements indicates how many elements are in the corresponding element of the matrix. The code tests for successful memory allocation, but does not react to allocation failure.
int num_elements = 1234; // whatever
struct myArray *myMatrix;
myMatrix = malloc (num_elements * sizeof (*myMatrix));
if (!myMatrix)
// error
// subsequent use of myMatrix is just like it had been statically dimensioned:
myMatrix [0].someData = 343;
myMatrix [1].someData = 323;
You need to use malloc and free functions to dynamically allocate and free the memory. Please use the following as a reference.
#include <stdio.h>
#include <stdlib.h>
int main()
{
struct myElement {
int field1;
int field2;
int field3;
};
struct myArray {
struct myElement *elements;
int someData;
};
struct myArray *myMatrix = NULL;
int n_myarray = 0;
int n_elements = 0;
int i, j;
printf("How many myArray's do you want? ");
scanf("%d", &n_myarray);
printf("How many elements do you want in each array? ");
scanf("%d", &n_elements);
/* memory allocation starts here */
if ((myMatrix = (struct myArray *) malloc((int)sizeof(struct myArray) * n_myarray)) == NULL) {
printf("ERROR: unable to allocate array\n");
return 1;
}
for (i=0 ; i<n_myarray ; i++) {
if ((myMatrix[i].elements = (struct myElement *) malloc((int)sizeof(struct myElement) * n_elements)) == NULL) {
printf("ERROR: unable to allocate array elements\n");
free(myMatrix);
return 1;
}
/* initialization of other members of struct myArray goes here */
myMatrix[i].someData = 123;
/* initialization of members of struct myElement goes here */
for (j=0 ; j<n_elements ; j++) {
myMatrix[i].elements[j].field1 = 123;
myMatrix[i].elements[j].field2 = 123;
myMatrix[i].elements[j].field3 = 123;
}
}
/* do your calculations here */
/* I'm printing the values */
for (i=0 ; i<n_myarray ; i++) {
printf("myMatrix[%d].someData : %d \n", i, myMatrix[i].someData);
for (j=0 ; j<n_elements ; j++) {
printf("myMatrix[%d].elements[%d].field1 : %d \n", i, j, myMatrix[i].elements[j].field1);
printf("myMatrix[%d].elements[%d].field2 : %d \n", i, j, myMatrix[i].elements[j].field2);
printf("myMatrix[%d].elements[%d].field3 : %d \n", i, j, myMatrix[i].elements[j].field3);
}
}
/* memory deallocation (free) starts here */
for (i=0 ; i<n_myarray ; i++) {
free(myMatrix[i].elements);
}
free(myMatrix);
return 0;
}
> ./a.out
How many myArray's do you want? 2
How many elements do you want in each array? 5
myMatrix[0].someData : 123
myMatrix[0].elements[0].field1 : 123
myMatrix[0].elements[0].field2 : 123
myMatrix[0].elements[0].field3 : 123
myMatrix[0].elements[1].field1 : 123
myMatrix[0].elements[1].field2 : 123
myMatrix[0].elements[1].field3 : 123
myMatrix[0].elements[2].field1 : 123
myMatrix[0].elements[2].field2 : 123
myMatrix[0].elements[2].field3 : 123
myMatrix[0].elements[3].field1 : 123
myMatrix[0].elements[3].field2 : 123
myMatrix[0].elements[3].field3 : 123
myMatrix[0].elements[4].field1 : 123
myMatrix[0].elements[4].field2 : 123
myMatrix[0].elements[4].field3 : 123
myMatrix[1].someData : 123
myMatrix[1].elements[0].field1 : 123
myMatrix[1].elements[0].field2 : 123
myMatrix[1].elements[0].field3 : 123
myMatrix[1].elements[1].field1 : 123
myMatrix[1].elements[1].field2 : 123
myMatrix[1].elements[1].field3 : 123
myMatrix[1].elements[2].field1 : 123
myMatrix[1].elements[2].field2 : 123
myMatrix[1].elements[2].field3 : 123
myMatrix[1].elements[3].field1 : 123
myMatrix[1].elements[3].field2 : 123
myMatrix[1].elements[3].field3 : 123
myMatrix[1].elements[4].field1 : 123
myMatrix[1].elements[4].field2 : 123
myMatrix[1].elements[4].field3 : 123
>
Please ensure the following:
for every malloc there should be a free
before using the memory that was allocated using malloc you must check whether malloc successfully allocated the memory block you've requested.
Something like this should work though it is not a great solution with so many seperate allocations, further down is a better solution. I have tried to make variable names descriptive of what they hold.
int arrayOfSubArrayLengths={9,5,10,50,...};
int lengthOfMyMatrix=something;
myMatrix= (myArray*) malloc( sizeof(myArray) * lengthOfMyMatrix);
for(int i=0; i<lengthOfMyMatrix; ++i)
{
myMatrix[i].elements=new myElement[arrayOfSubArrayLengths];
myMatrix[i].someData=whatever;
}
to delete:
for(int i=0; i<lengthOfMyMatrix; ++i)
{
free( myMatrix[i].elements );
}
free( myMatrix );
However as I said that is not a great solution with so many allocations. It could cause some severe memory fragmentation depending on how large lengthOfMyMatrix is. Also so many calls to the allocator could slow things down depending once again on the size of lengthOfMyMatrix.
Here is a better solution:
int arrayOfSubArrayLengths={9,5,10,50,...};
int lengthOfMyMatrix=something;
int sumOfSubArrayLengths=someNumber;
myArray* fullArray=(myElement*) malloc( sizeof(myElement) * sumOfSubArrayLengths);
myMatrix= (myArray*) malloc( sizeof(myArray) * lengthOfMyMatrix);
int runningSum=0;
for(int i=0; i<lengthOfMyMatrix; ++i)
{
myMatrix[i].elements = &fullArray[runningSum];
runningSum += arrayOfSubArrayLengths[i];
myMatrix[i].someData = whatever;
}
to delete:
free( fullArray );
free( myMatrix );
In this fashion there are only two calls to the allocator no matter the various lengths. So there is far more memory fragmentation and less allocation overhead time.
The one downside to the second method is that if you are not careful with bounds checking it is very easy to corrupt data in the array without knowing since the memory 'belongs' to you and thus the OS will not kick you for an access violation.

C Programming weird struct setup

I am trying to build this project and for some reason the program hangs when I run it.
It works fine if i comment out the data cache lines. but it cannot make a call to makeCache for two different caches i dont know why any C experts know. Im new to c.
/*
* main.c
*
* Created on: Sep 16, 2010
* Author: TJ
*/
#include <stdlib.h>
#include <stdio.h>
typedef struct {
int tag;
int valid;
int LRU;
int offset;
}directoryBlock;
typedef struct{
int setNumber;
directoryBlock blocks[];
}cacheSet;
typedef struct{
int cacheNumber;
cacheSet *sets[];
}cache;
cache* makeCache(cache *makeMe,int numberOfSets, int blocksPerSet);
int main(void)
{
int i = 0;
//cache * temp = makeCache(10,200);
i = 0;
int j = 0;
cache *instructions = malloc(sizeof(cache) + sizeof(cacheSet*));
cache *data = malloc(sizeof(cache) + sizeof(cacheSet*));
makeCache(instructions,20,300);
makeCache(data,20,300);
for(j=0;j < 20;j++)
{
for(i = 0; i < 300;i++)
{
printf("Data From Set %d Block %d, Valid %d, Tag %d, LRU %d, Offset %d\n",j,i
,instructions->sets[j]->blocks[i].valid,instructions->sets[j]->blocks[i].tag
,instructions->sets[j]->blocks[i].LRU,instructions->sets[j]->blocks[i].offset);
}
}
return 0;
}
cache* makeCache(cache *makeMe,int numberOfSets,int blocksPerSet)
{
int i = 0;
int j = 0;
for(j=0; j < numberOfSets;j++)
{
cacheSet *newSet = malloc(sizeof(cacheSet) + sizeof(directoryBlock)*blocksPerSet);
for(i = 0; i < blocksPerSet; i++)
{
directoryBlock temp;
temp.LRU = i*j;
temp.tag = i*j;
temp.offset = i*j;
temp.valid = i;
newSet->blocks[i] = temp;
}
makeMe->sets[j] = newSet;
}
return makeMe;
}
You're not allocating space for the cacheSet array, you have 20 cacheSets so try this with the "20 *" added to your lines:
cache *instructions = malloc(sizeof(cache) + 20 *sizeof(cacheSet*));
cache *data = malloc(sizeof(cache) + 20 * sizeof(cacheSet*));
In your main function you're allocating the memory for your cache. Since you have a function dedicated to creating the cache, it should allocate the memory. That function has the parameters to determine the total memory required. If you do it separately, you're repeating that information and require yourself to remember exactly how to allocate the memory. If the function makeCache does it for you, it will save pain later. Just be sure your documentation notes that the makeCache function allocates memory.
Your cache memory is incorrect, but not as pointed out before. Just sizeof(cache) is the right size. This will make room for the int and the cacheSet **. You should then allocate memory for the cacheSet array in each cache. Then you should allocate memory for each directoryBlock in each cacheSet in the cache.... kittens, cats, sacks, and wives...
So all your allocations should just be Thing *t sizof(Thing);
In psuedocode:
cache *c = malloc(sizeof(cache))
for 0 to number of cacheSets:
cacheSet *s = malloc(sizeof(cacheSet))
for 0 to number of blocks:
block *b = malloc(sizeof(block))
//fill in data
JD

Resources