Accesing values on a 2d struct array - c

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 */

Related

A pointer to the array in a struct

The first parameter of qsort requires a pointer to the array ...
How could I pass the pointer in this case?
typedef struct apData {
char ssid[32];
sint8 rssi;
AUTH_MODE authmode;
char bssid[18];
int32_t channel;
uint8 is_hidden;
} AP;
//BSSs SCANNED
typedef struct {
bool scanInProgress = NOT_SCANNING;
AP **apData;
int numAPs;
} Scan;
static Scan scanAPs;
...
The problem is here in passing the first parameter ...
I don't understand why I'm getting trash in the compareRSSI() function
qsort(scanAPs.apData, scanAPs.numAPs, sizeof(struct apData), compareRSSI);
...
int compareRSSI(const void *bss1, const void *bss2) {
int firstAP = ((struct apData *)bss1)->rssi;
int secondAP = ((struct apData *)bss2)->rssi;
return (secondAP - firstAP);
}```
You're passing to qsort a pointer to an array of pointers (apData is of type AP**), but you're saying that each element of the array is sizeof(struct apData) (as if it were an array of structures). So which is it?
You didn't show how you assigned scanAPs.apData a value, and you didn't show where you allocated storage for the elements of the array to be sorted. So, unfortunately, it's unclear if you intended to be sorting an array of pointers or if you intended to have an array of apData structures.
If the type declaration is correct and you have an array of pointers...
Since the type of apData is AP **, then you would have had an array of pointers to structures somewhere. In which case your sort call should have looked like:
qsort(scanAPs.apData, scanAPs.numAPs, sizeof(struct apData*), compareRSSI);
Note that the sizeof indicates that each element of the array is a pointer.
If the type declaration is wrong and you have an array of structures...
If it's the type that is wrong, then you need to change the type of apData to just AP*, and set it equal to the pointer to the first structure in the array. You'll need to assign an appropriate value somewhere and verify that you allocated storage for the array correctly too.
Do not use a C-style cast when assigning apData a value because the compiler will ensure that you have the right type.
Here's, My solution! these guys helped me a lot.
link!
qsort(scanAPs.apData, scanAPs.numAPs, sizeof(struct apData*), compareRSSI);
...
int compareRSSI(const void *bss1, const void *bss2) {
struct apData **firstAP = (struct apData **)bss1;
struct apData **secondAP = (struct apData **)bss2;
return ((*secondAP)->rssi - (*firstAP)->rssi);
}

Access value from a pointer to a pointer

I am trying to access a field from a struct through a pointer of pointer
I tried:
(**vform).vpolygon->point->x = 1;
But doesn't worked.
code:
typedef struct point{
int x;
}point;
typedef struct polygon{
point *point;
}polygon;
typedef struct form{
polygon **polygon;
}form;
void main(){
polygon *vpolygon;
form **vform;
vpolygon = (polygon *)malloc(sizeof(polygon)*5);
vform = (form **)malloc(sizeof(form)*5);
vpolygon->point->x = 1;
vform->vpolygon->point->x = 1;
}
I expect the program compile, but the actual output is
18:12: error: '*vform' is a pointer; did you mean to use '->'?
vform->vpolygon->point->x = 1;
^~
->
The code below should compile in what you seem to want. There are however a lot of issues with what you're doing that may not be immediately obvious, but I'll go into that a little below.
typedef struct point {
int x;
} point;
typedef struct polygon {
// dynamically allocated array of point
point *point;
} polygon;
typedef struct form {
// dynamically allocated array of polygon
polygon *polygon;
} form;
form *vform;
vform = malloc(sizeof(form) * 5);
vform->polygon = malloc(sizeof(polygon) * 5);
vform->polygon->point = malloc(sizeof(point) * 5);
vform->polygon->point->x = 1;
First issue is that you're mixing up your variables with the members of your structures. Your form structure has no element called "vpolygon". Just because your "vpolygon" variable is a polygon structure doesn't mean you can suddenly refer to the polygon member of a form variable by calling it "vpolygon".
Secondly, you're casting the return value of malloc. Don't do this. See do I cast the result of malloc
Thirdly, your form malloc is allocationing enough memory for 5 form structures, but casting the result to a pointer to a pointer to form. The malloc should possibly be malloc(sizeof(form *) * 5) but I'm guessing you really meant (vform *)malloc... not (vform **)malloc....
Fourth, you're dynamically allocating arrays and pointing your variables at the first element in the array but you don't seem to have any mechanism to detect the size of the array. You need a method to track the size of the array so you don't accidentally cause a segmentation fault by going off the end of the array. (Three common methods: 1) track the number of elements allocated. 2) Mark the end of the array with some marker value and check for if, 3) hard-code it. All have trade-offs)
Fifth. You want to store the original value returned by malloc so you can free it at some point - if you modify what vfrom points to you'll lose that original address and cause memory leaks.

C structure pointer to a structure array, from a structure

I need some help with the pointer syntax. I have an array of structures, and I'm trying to create a pointer to it, from inside another structure, contained in an array.
struct foo array* = malloc(sizeof(foo)*10);
bar_arr[i]->foo_ptr = &array;
I have read through this question: c pointer to array of structs. While it did clear up some of the confusion, I'm still left with a few errors to solve.
I have defined my structure like this:
struct bar{
...
struct foo (*foo_ptr)[];
...
}
It seems that I am able to add new structures to the array, as the following returns no errors:
(*bar_arr[i]->foo_ptr)[j] = new_struct;
However, if I attempt to create a new pointer to a struct inside of the struct array like this:
struct foo* one_ptr = (*bar_arr[i]->foo_ptr)[j];
or this:
struct foo* one_ptr = bar_arr[i]->foo_ptr[j];
the compiler will give me errors. Either one for invalid use of an array with unspecified bounds, or that one_ptr and foo_ptr[j] have incompatible types (in this case: one is of type foo and the other is struct foo *).
Is it simply not possible to create a pointer to one of the elements of the structure array? Any help would be appreciated.
EDIT: BETTER CODE EXAMPLE
I am currently working with a linearly linked list for use as a shared memory stack, for use with pthreads. The array of structures is a shared pool of nodes. Whenever a node is removed from the stack, it is put into the shared pool. If a thread attempts to add a new item to the stack, it checks whether or not the element to be added exists in the pool, to avoid having to allocate new memory every time it needs to add another element to the stack.
Each thread needs a pointer to the shared pool of nodes as an argument. That's why i'm trying to create a pointer to it from the argument structure. I was hoping that the question would have a simple answer.
typedef struct node{...} node_t;
struct thread_args
{
...
node_t (*pool)[];
...
}
node_t shared_pool = malloc(sizeof(node_t)*10);
arg[index]->pool = &shared_pool;
I am trying to access the pool inside one of the functions that the thread is executing.
node_t *item;
item = stack->root;
//remove item from stack
(*args->pool)[index] = item;
//...later
node_t *item2;
item2 = (*args->pool)[index];
Hopefully this provides some more information.
Also, the exact error i get from attempting to use:
node_t *pool;
args[index]->pool = shared_pool;
is as follows: error: incompatible types when assigning to type ‘struct node_t *’ from type ‘node_t’.
For starters this declaration (not mentioning the omitted semicolon after the closing brace)
struct bar{
...
struct foo (*foo_ptr)[];
^^^
...
}
is invalid. You have to specify the size of the array. Otherwise the pointer will point to an object of an incompete type.
Taking into account how you are trying to use the array this declaration does not make sense. You could declare the data member like
struct bar{
...
struct foo *foo_ptr;
...
};
and then
struct foo *array = malloc(sizeof(struct foo)*10);
bar_arr[i]->foo_ptr = array;
In this case you could write
bar_arr[i]->foo_ptr[j] = new_struct;
and
struct foo* one_ptr = bar_arr[i]->foo_ptr + j;
or
struct foo* one_ptr = &bar_arr[i]->foo_ptr[j];
This is wrong:
struct foo array* = malloc(sizeof(foo)*10);
bar_arr[i]->foo_ptr = &array;
Assuming you mean
struct foo *array = malloc(sizeof(foo)*10);
bar_arr[i]->foo_ptr = &array;
you are storing the address of the actual array variable into your structure's foo_ptr variable. From the code snippet you posted, that's likely a local variable for the function, so it's not only the wrong type, it ceases to exist once your function returns.
Given struct foo, this will allocate a pointer to an array of struct foo:
struct foo *array = malloc( nelem * sizeof( *array ) );
and this will assign that
bar_arr[i]->foo_ptr = array;
Or, more directly:
bar_arr[i]->foo_ptr = malloc( nelem * sizeof( *( bar_arr[i]->foo_ptr ) ) );
Note that I use a dereference to the pointer the malloc() result is being assigned to as the argument to sizeof(). That's a simple way to ensure that the pointer and the memory allocation done always refer to the same type.
The call to malloc() will allocate nelem contiguous copies of struct foo (which will contain unknown, unspecified data...). Those copies can be accessed via
array[ n ]
as long as n >= 0 and n < nelem.
Is it simply not possible to create a pointer to one of the elements of the structure array?
You're making your code too complex. To create a pointer to the nth element:
struct foo *nthElement = array + n;
You simply add n to the address of the first element, and the resulting pointer will refer to the nth element, assuming n is within the proper range.
Short answer
The declaration of foo_ptr in struct bar is not right. Change it into struct foo *foo_ptr. And change your assigning statement to the follows
struct foo *array = malloc(sizeof(struct foo)*10);
bar_arr[i]->foo_ptr = array;
Then you can read or write the element of the array like below
// read from array
struct foo one_struct = bar_arr[i]->foo_ptr[j];
// write to array
struct foo new_struct = { ... }
bar_arr[i]->foo_ptr[j] = new_struct;
(NOTE: the both read and write operation are copy of all fields of the struct foo).
Explanation of the changes
Think about an easy example. How do you make an array of 10 char.
char *a = malloc(sizeof(char)*10)
a is a pointer of char, it points to a space that contains 10 char. So we can use it as an array. a[4] means the 5th char of the array of 10 char.
What if you want to assign this array to another variable?
char *b = a;
Now b is an array too (not a copy of the original array, b and a point to one array). You can refer to the element via b now, just like what you do with a. E.g., b[4].
Nobody will declare b as char (*b)[] right?
More explanation of your mistakes
Still start with an simple example. When we see such a declaration -- char (*x)[10] -- what would we say about x? We may say x is a pointer to an array of 10 char.
Let's look at your declaration, struct foo (*foo_ptr)[]. Likewise, we may say, foo_ptr is a pointer to an array of ... length-unspecified struct foo. (Notice the difference in the length of array. Actually it is wrong not to specify the length, I'll talk about it soon)
Based on this declaration of yours, let's talk about the errors you encountered when using it.
Statement 1 that throws error
struct foo* one_ptr = (*bar_arr[i]->foo_ptr)[j];
To simplify and make it clear, I'm going to remove the part of bar_arr[i]-> in following discussion.
In this statement, *foo_ptr is an array of length-unspecified struct foo, we can call it this way, *foo_ptr is an array of struct foo []. So (*foo_ptr)[j] means the jth element of the array of struct foo []. Everything seems good here. BUT your array has no length defined, even though you assigned a malloc'ed array to it, but in compile-time, gcc has no idea about it. That is why it throws an error about "unspecified bounds".
Statement 2 that throws error
struct foo* one_ptr = bar_arr[i]->foo_ptr[j];
As I said above, foo_ptr is a pointer to an array of struct foo []. Let's pay attention to the fact that foo_ptr is a pointer first. So in this statement, foo_ptr[j] is kinda like *foo_ptr. Other than the index j, they have same type. Since we already know *foo_ptr is an array of struct foo [], foo_ptr[j] is also an array of struct foo []. It's an array, not an object of struct foo. To put it precisely, you need to imagine there is a big array, of which each element is still array (array of struct foo []). foo_ptr[j] is just the jth element, or say jth array, in this big array.
So the practice you assign foo_ptr[j] to one_ptr is more or less like the following example
typedef char char_array_of_4_t[4];
char_array_of_4_t array1;
char *p = array1; //ERROR: incompatible types
To make it easy to understand, I show you another exmaple below.
char array2[4];
char *p = array2;
In the second example, there is no error. In perspective of human being, array1 and array2 are both array of 4 char, however, in mind of gcc, array1 is a type of array, while array2 is a type of pointer.
In this declaration ...
struct bar{
// ...
struct foo (*foo_ptr)[];
// ...
};
... member foo_ptr of struct bar is declared as a pointer to an unknown-length array of struct foo. This is allowed, but it is unusual. One would ordinarily just declare a pointer to the first element of the array, as this plays out more naturally in C, and it's simpler, too:
struct bar{
// ...
struct foo *foo_ptr;
// ...
};
You can assign to the members of the pointed-to array via this form:
bar_arr[i]->foo_ptr[j] = new_struct;
(provided of course, that the pointed-to array has at least j + 1 elements. To get a pointer to such an element, you would do either
struct foo *struct_ptr = &bar_arr[i]->foo_ptr[j];
or, equivalently,
struct foo *struct_ptr = bar_arr[i]->foo_ptr + j;
You can do the same with your original struct declaration, but the form would need to be slightly different. For example:
struct foo *struct_ptr = &(*bar_arr[i]->foo_ptr)[j];
But really, make it easier on everybody, yourself included, and don't do that.

Pointer to Two Dimensional Structure Array

I have a Structure say MyStruct:-
#define SEC_DIMENSION 2
struct MyStruct
{
char cChar;
float fFloat;
int iInt;
};
struct MyStruct StructArray[SEC_DIMENSION][20]; //Two Dimensional Array of Structures.
Now I want to access this with Pointer.
struct MyStruct *StructPtr[SEC_DIMENSION];
I did assignment as follows:-
StructPtr[0] = &StructArray[0][0];
Now, I want to access Members of Structure StructArray[0][1] i.e. StructArray[0][1].cChar or StructArray[0][1].fFloat
How can I access them by using StructPtr?
I tried using StuctPtr[0][1]->cChar then ((StructPtr[0])[1])->cChar
Both returned an error.
With StructPtr[0]->cChar build was successful. But this is not what I want.
"Now I want to access this with Pointer" is not very descriptive. What you have in your example will not work. What you declared is not a pointer to an array but rather an array of pointers. Is that what you need? I don't know.
If you really need a pointer to an array, you can declare your pointer it as
struct MyStruct (*StructPtr)[20];
and then make it point to your array as
StructPtr = StructArray;
From this point on you can access the original array through this pointer as StructPtr[i][j]
StructPtr[i][j].cChar = 'a';
Alternatively, you can declare the pointer as
struct MyStruct (*StructPtr)[SEC_DIMENSION][20];
and then make it point to your array as
StructPtr = &StructArray;
From this point on you can access the original array through this pointer as (*StructPtr)[i][j]
(*StructPtr)[i][j].cChar = 'a';
I think you need a "pointer to an array of dimension [SEC_DIMENSION][20] of structures of type struct MyStruct":
struct MyStruct (*StructPtr)[SEC_DIMENSION][20];
StructPtr = StructArray;
StructPtr[i][j]->cChar;

c how to make a dynamic array pointer in a struct

I am taking in input from the user for the number of elemenets inside an array. The array is inside my struct 'Polymer'
struct Polymer
{
int length;
struct Monomer *monomer;
}polymer;
In main, I am creating a new monomer array pointer and setting the mononomer pointer in "Polymer" to it
struct Monomer *monomers[size];
polymer.monomer = momomers;
I am getting the error "Assignment from incompatible pointer type" which I assume is because we are converting a monomer array pointer to a monomer. How do I declare it as a monomer array pointer in the struct?
You are declaring an array of monomer pointers when you probably want an array of monomers. Drop the *:
struct Monomer monomers[size];
polymer.monomer = momomers;
struct Monomer *monomers[size];
polymer.monomer = momomers;
monomers is an array of pointers. They aren't pointing to any valid locations and has garbage values. While Polymer::monomer is a pointer. Array of pointers isn't type compatible to just a pointer.
Instead try -
struct Monomer monomers[size];
polymer.monomer = momomers; // 2
Now this statement 2 is valid because array decays to a pointer.

Resources