I have a struct with an int array inside that I'm passing to a function for the array to be initialized
array struct like so..
typedef struct Container{
struct intArray *P;
int length;
} Container;
typedef struct intArray{
int *array;
int length;
} intArray;
function to initialize the array
like so...
int Initializer(intArray *myStruct, int n)
{
myStruct->array = malloc(sizeof(int) * (lengthOfint);
^
If n=55 then length would be 2
//let's just say n=5
myStruct->array[0] = n;
//return 1 if successful
return 1;
}
In another function I am calling the initializer function like so...
Container *myContainer = malloc(sizeof(Container));
myContainer->P = malloc(sizeof(intArray *) * Some_Defined_Value);
Initializer(&myContainer, 5);
printf("the data that should be at index 0 -> %d\n", myContainer->P.array[0];
I would think that the printf statement would print out 5 but it prints out garbage of varying numbers every time I compile it. I don't think I have a grasp of the array within a struct within a struct idea.
You pass the container to the initializer function, but if you look closely you'll see that the you are passing a pointer to a pointer to the "outer" container instead of a pointer to the desired struct intArray. You'd want something like Initializer(myContainer->P, 5);
Container holds a pointer to struct intArray, which in this case is the start of an array of struct intArray. But then you initialize this pointer with
malloc(sizeof(intArray *) * Some_Defined_Value);
So malloc returns a pointer to a memory space which holds pointers to struct intArray because you used sizeof(intArray *) and not sizeof(intArray) (you allocated space for Some_Defined_Value number of pointers).
You need sizeof(intArray) * Some_Defined_Value here to allocate space for Some_Defined_Value number of struct intArray's.
Then you use
Initializer(&myContainer, 5);
which should at least give a warning because you pass a pointer to a pointer to a struct Container, but Initializer expects a pointer to a struct intArray, so this is not what you want. To initialize the first element of your array of struct intArray's use:
Initializer(&(myContainter->P[0]), 5);
Then:
printf("the data that should be at index 0 -> %d\n", myContainer->P.array[0]));
This code does not compile because it should be:
printf("the data that should be at index 0 -> %d\n", myContainer->P[0].array[0]);
myContainer->P accesses a pointer to a struct intArray. The code right above means you access the first element (element number 0) of the array of struct intArray's .
To initialize/access the second element of the array of struct intArray's use:
Initializer(&(myContainter->P[1]), 5);
printf("the data that should be at index 0 -> %d\n", myContainer->P[1].array[0]);
Also be aware that malloc returns a void * so most of the time you'll need a cast like so:
myStruct->array = (int*)malloc(sizeof(int) * (length);
// ^^^^^^
Assuming length is the number of int you want to store in your array.
Related
Let's say I have the following struct and array of that struct:
struct Fileinfo {
int ascii[128]; //space to store counts for each ASCII character.
int lnlen; //the longest line’s length
int lnno; //the longest line’s line number.
char* filename; //the file corresponding to the struct.
};
struct Analysis fileinfo_space[8]; //space for info about 8 files
I want to have a function that will add a new struct to this array. It must take a void pointer to the position where to store the struct as an argument
int addentry(void* storagespace){
*(struct Fileinfo *)res = ??? //cast the pointer to struct pointer and put an empty struct there
(struct Fileinfo *)res->lnlen = 1; //change the lnlen value of the struct to 1
}
My questions are:
What goes in place of ??? I tried (Fileinfo){NULL,0,0,NULL} as per this Stackoverflow response. But I get `error: ‘Fileinfo’ undeclared (first use in this function)
How do I create a void pointer to the array? Is (void *)fileinfo_space correct?
I am required to use void * as the argument for the function for this assignment. It's not up to me.
Let's say you have some memory block passed as storagespace void pointer:
You have to define a constant to be able to initialize (unless you're using c++11), let's call it init. BTW your assignment value is wrong: first member is an array of int. You cannot pass NULL to it. Just zero-fill it like show below.
Then cast your void pointer into a pointer on your struct, then initialize by copying the init struct, modify at will...
int addentry(void* storagespace){
static const struct Fileinfo init = {{0},0,0,NULL};
struct Fileinfo *fi = (struct Fileinfo *)storagespace;
*fi = init; //cast the pointer to struct pointer and put an empty struct there
fi->lnlen = 1; //change the lnlen value of the struct to 1
}
So I have this struct
struct cell
{
int downwall;
int rightwall;
};
I have dynamically allocated memory for a 2d array of struct cell
(struct cell ** array)
However when I try to access a certain cell with the command
array[i][j] -> downwall = 0;
I get this error:
invalid type argument of '->' (have 'struct cell')
Use
array[i][j].downwall = 0;
instead.
You would have used -> if arrray[i][j] had type struct cell* which it doesn't have. It has type struct cell.
The type of array[i][j] will be of struct cell, not struct cell *. You should use the . operator to access a member.
You need to write
array[i][j].downwall = 0; // use of .
Please note that
struct cell** array
is not a 2D array! it is a pointer to a pointer of type 'struct cell'.
You should regard it as a 2D array only if there is an allocated memory to which the values point (Statically or dynamically). Otherwise, you are on the road for a Segmentation Faults.
Your struct is not a pointer struct so simply do something like:
//array cells of type cell and can hold 10 cell's
struct cell cells[10];
//Try using malloc for memory allocation
cells[0] = (struct cell *) malloc(sizeof(struct cell));
//example assignment
cells[0].downwall=0;
cells[0].rightwall=1;
You need to declare an actual array with the right number of indices, then make the pointer point to it. Use typed names to help ( simplified Hungarian Notation )
int iAry[M][N];
int **ptrAry;
ptrAry = iAry; /* equivalent to ptrAry = &iAry[0][0]; */
/* then use -> operator as you have done */
I have
the struct:
typedef struct Rental {
int nDays;
float kmsDriven;
char carLicensePlate[LICENSE_PLATE_LENGTH+1];
char *clientName;
char chargingCategory;
} Rental;
Different -Rental type- structs are stored and accessed via a dynamically allocated array of pointers (here is a part of the project):
int main (){
Rental *rentals;
int max_num;
printf("Give a number of rentals you would like to store and manage: ");
scanf("%d", &max_num);
rentals=(Rentals *)malloc(max_num * (sizeof(Rental)))
This is what I have thought of so far but I can't understand it completely...so:
I'm having trouble understanding how *rentals can be an array. I mean shouldn't I declare it at least this way: Rental *rentals[];? I know that if I compile the above code I will see an error...but why?
I've read numerous posts here in Stack Overflow about doing this with double pointers (Rental **rentals;) but the code other people have posted is often very hard for me to read (I don't know all the functions etc. etc.)
Let's say I have the object rentals[0] which will be a pointer towards rentals. If I wanted to pass the struct to a function, should I write:
variable=function(*arguments*... , Rental *rentals[0]);?
rentals is a pointer, not an array, but it is a pointer to the first (zeroth) element of a block of max_num structures, so it can be treated as an array in that you can use rentals[n] to refer to the nth element of the array.
This is not a question and hence it is unanswerable.
Let's say I have the object rentals[0] which will be a pointer towards rentals. If I wanted to pass the struct to a function, should I write: variable=function(*arguments*... , Rental *rentals[0]);?
rentals[0] is not a pointer; it is a struct Rental or Rental.
If you want to pass the structure to the function, you write:
variable = function(…args…, rentals[0]);
If you want to pass a pointer to the structure to the function, you write:
variable = function(…args…, &rentals[0]);
or:
variable = function(…args…, rentals);
These pass the same address to the function.
You should be error checking the call to scanf() to make sure you got a number, and you should error check the number you got (it should be strictly positive, not zero or negative), and you should error check the value returned by malloc().
When you declare an array (for example char buffer[10]; the variable is actually pointing to that array. Pointers and arrays are very close together. In fact when you have a pointer where you store an array of data (just like your case with malloc) you can do something like pointer[0] and pointer[1] to get the correct element.
With a pointer in order to access an element you'd normally use *(pointer +1) to get the element on position 1, this is exactly the same as pointer[1].
When you want to pass a struct in an array, you can either give it by value like this:
void function(struct mystruct var)
{
//...
}
int main()
{
struct mystruct var;
function(var);
}
Or by reference (passing the address instead of the data - this is ideal if your structs are big in size) :
void function(struct mystruct *var)
{
//...
}
int main()
{
struct mystruct var;
function(&var);
}
By using an array, you can do it like this (still by reference):
void function(struct mystruct *var)
{
//...
}
int main()
{
struct mystruct var[10];
function(&var[0]);
}
And using a pointer (to an array) :
void function(struct mystruct *var)
{
//...
}
int main()
{
struct mystruct *var;
var = malloc( sizeof(struct mystruct) *10 );
//This will pass the address of the whole array (from position 0)
function(&var);
//This will pass the address of the selected element
function(&var[0]);
}
As you can see, declaring an array or a pointer is almost the same, expect that you have to initialize the pointer-array yourself (with malloc) and as with anything created with malloc you have to free it yourself too.
I understand the difference between memory allocation using malloc for an array of struct and for an array of pointers to struct. But I want to assign memory using malloc for an array of struct, in the case that the struct itself contains a pointer to another struct. Here is the code for what I am trying to do:
#include<stdio.h>
#include<stdlib.h>
typedef struct linkedlist {
int pCol;
struct linkedlist *next;
} plist;
typedef struct particle {
int color;
double rad;
double rx;
double ry;
double vx;
double vy;
struct linkedlist *event;
} state;
int main()
{
int N = 5, w = 4;
plist *ls = (plist*)malloc((N+w)*sizeof(plist));
printf("N=%d, w=%d, sizeof state=%d, total=%d, sizeof discs=%d\n\n",
N,w,sizeof(plist), (N+w)*sizeof(plist), sizeof(ls));
state *discs = (state*)malloc((N+w)*sizeof(state));
printf("N=%d, w=%d, sizeof state=%d, total=%d, sizeof discs=%d\n",
N,w,sizeof(state), (N+w)*sizeof(state), sizeof(discs));
return 0;
}
When I run this, I get the following output:
N=5, w=4, sizeof plist=8, total=72, sizof ls=4
N=5, w=4, sizeof state=56, total=504, sizof discs=4
So, I want to know why does the ls or the discs get assigned only 4 bytes and how can I get total memory required assigned for these arrays of structs?
You are printing size of pointer(ls) and not size of datatype/structrure pointed by the pointer (*ls).
Do sizeof(*ls) and sizeof(*discs) in your printf statements if you intend to find size of plist and state because that is where ls and discs point to.
If you are thinking of printing the total size allocated to ls or discs by malloc. That is not possible. Its not going to print ((N+w)*sizeof(plist)).
So even doing sizeof(*ls) is not going to tell you how many plist structures you allocated
in your code, ls is of type plist *,.i.e., a pointer.
sizeof() is an operator which returns the size of the data type, not the amount of memory allocated.
Same goes for discs.
I just wanted to know if the following works. I have a struct
called foo that is defined as the following:
struct foo {
char name[255];
int amount;
};
During runtime, I need to create an array of the above structures whose size is dependent on a value I receive from a file's input. Let's say this size is k. Will the following code appropriately allocate a dynamically-sized array of structures?
struct foo *fooarray;
fooarray = malloc(k * sizeof(struct foo));
EDIT: If I want to access members of the structures within these arrays, will I use the format fooarray[someindex].member?
That will work (and your accessing is correct). Also, you can guard against size errors by using the idiom:
fooarray = malloc(k * sizeof *fooarray);
Consider using calloc if it would be nice for your items to start out with zero amounts and blank strings, instead of garbage.
However, this is not a VLA. It's a dynamically-allocated array. A VLA would be:
struct foo fooarray[k];
Yes it will.
On failure it will return 0.
And you have to free the memory returned by malloc when you are done with it
You can access the first member:
fooarray[0].name
fooarray[0].amount
The second as:
fooarray[1].name
fooarray[1].amount
etc..
One more different notation can be used in this approach:
struct foo {
char name[255];
int amount;
};
int main (void)
{
struct foo *fooarray;
struct foo *fooptr[5];
unsigned int i = 0;
for (i = 0; i < 5; i++)
fooptr[i] = malloc(1* sizeof(struct foo));
fooptr[2]->name[3] = 'A';
printf ("\nfooptr[2]->name[3]=%c\n",fooptr[2]->name[3]);
}