Assign value at pointer value from void pointer - c

I have two void pointers inside structures.
typedef struct DATA_T {
BOOLEAN trigger;
void *var_p;
void *data_p;
} DATA_T;
typedef struct ITEM_T {
DATA_T job_data[100];
BOOLEAN job_active;
BOOLEAN job_send;
} ITEM_T;
ITEM_T foo[100];
I assigned the two void pointers to different addresses. Now, I have a value at one pointer and want to set the other pointer = to that value.
foo[i].job_data[j]->data_p = *(int*)foo[i].job_data[j].var_p;
This error is then posted:
error C2232: '->data_p' : left operand has 'struct' type, use '.'
I don't believe I want a . in place of the -> here, because I need to dereference the pointer data_p.
Thanks for your assistance.

The error message is because job_data[j] is not a pointer. It is a DATA_T. So the left-hand side should be foo[i].job_data[j].data_p = .
However there is another error. On the right-hand side, *(int *) produces an int, which cannot be stored in a void *.
If you want to make the two pointers point to the same place then remove the *(int *).
If both pointers actually point to ints, and you want to copy the pointed-to value on both sides, then put *(int *) on both sides.

Elements of job_data array are not pointers, they're in the type of DATA_T.

Related

Is this the correct way to make a pointer that points on an array of lists (structs)?

We have this struct:
typedef struct picture* picPtr
typedef struct picture{
int id;
int likes;
picPtr next;
}Picture;
And we have this function:
void add_picture(picPtr arr[], int id)
what i want to do in this function is make a temporary pointer to that array in a certain place(notice that this array is type picPtr making it an array of linked list meaning that each cell of that array has a linked list. so what i did is this:
picPtr* temp = (arr +id);
is this the correct way?
I wrote what I tried but I got points deducted in my exams, idk if its because of this.
Within a function declared this way ...
void add_picture(picPtr arr[], int id)
... identifier arr has type picPtr *, also known as struct picture **.
In such a context, this declaration ...
picPtr* temp = (arr +id);
... is syntactically valid, does not violate any language constraints, and is equivalent to:
picPtr *temp = &arr[id];
Whether that makes it correct is a separate question that we do not have sufficient information to answer. It may be perfectly valid, yet not suited for the intended purpose, for example. Or there might be other reasons for it to be unacceptable, such as issues with the value of id.
No, it is not a good way.
typedef struct picture* picPtr;Horrible habit of hiding the pointers behind the typedefs. Never do this (even for function pointers - better declare funtuon type and then use the usual pointer syntax).
. If you want to pass the pointer referencing the first element of the array:
void add_picture(Picture *arr, int id)
if you want to pass the pointer to pointer to Picture : void add_picture(Picture **arr, int id) (and not that it is not a pointer to the array).
Passing pointer to the array: void add_picture(size_t sizeOfArray, Picture (*arr)[sizeOfArray], int id)
picPtr* temp = (arr +id); I do not think that you want a pointer to pointer to Picture in this statement and as you hide the pointer behind the typedef, you have lost the track of what is referencing what.
If passed a pointer to Picture: Picute *temp = arr[id] or Picute *temp = arr + id
If passed a pointer to pointer to Picture:Picute *temp = (*arr)[id] or Picute *temp = (*arr) + id
If passed a pointer to array of Picture elements:Picute *temp = &arr[id]

Why does this pointer declaration work with malloc()?

I am new to C and have a question about a specific pointer declaration:
Here is a program i wrote:
#include <stdlib.h>
struct n {
int x;
int y;
};
int main()
{
struct n **p = malloc(sizeof(struct n));
return 0;
}
The declaration here is not be correct but why not?
Here is my thought process:
The man page of malloc specifies that it returns a pointer:
The malloc() and calloc() functions return a pointer to the
allocated memory, which is suitably aligned for any built-in
type.
The type of p is struct n** aka a pointer to another pointer.
But shouldn't this declaration work in theory because:
malloc returns type struct n* (a pointer)
and p points to the pointer that malloc returns
so it is essentially a pointer to another pointer
so the type of p is fulfilled
Sorry if this is a dumb question but i am genuinely confused about why this does not work. Thanks for any help in advance.
The return type of malloc is not struct n *, regardless of how it is called. The return type of malloc is void *.
Initializing a struct n ** object with a value of type void * implicitly converts it to struct n **. This implicit conversion is allowed, because the rules for initialization follow the rules for assignment in C 2018 6.5.16.1 1, which state one of the allowed assignments is:
… the left operand has atomic, qualified, or unqualified pointer type, and (considering the type the left operand would have after lvalue conversion) one operand is a pointer to an object type, and the other is a pointer to a qualified or unqualified version of void, and the type pointed to by the left has all the qualifiers of the type pointed to by the right;…
and p points to the pointer that malloc returns
No, the value p is initialized to the value that malloc returns. Then p points to the memory malloc allocated.
It is a mistake for this code to allocate enough space for a struct n (using malloc(sizeof(struct n))) but assign the address of that space to the struct n ** that is p. To point to a struct n, use struct n *p = malloc(sizeof (struct n)); or, preferably, struct n *p = malloc(sizeof *p);.
To pointer to a pointer to a struct n, first create some pointer to a struct n, as with the above struct n *p = malloc(sizeof *p);. Then a pointer to that pointer would be struct n **pp = &p;.
If you wanted to allocate space for those pointers-to-pointers, you could do it with struct n **pp = malloc(sizeof *pp);, after which you could fill in the pointer to the struct n with *pp = malloc(sizeof **pp);. However, you should not add this additional layer of allocation without good reason.
Note that the form MyPointer = malloc(sizeof *MyPointer); is often preferred to MyPointer = malloc(sizeof (SomeType)); because the former automatically uses the type that MyPointer points to. The latter is prone to errors, such as somebody misintepreting the type of MyPointer and not setting SomeType correctly or somebody later changing the declaration of MyPointer but omitting to make the corresponding change to SomeType in the malloc call.
This doesn't really work. In this example, malloc is returning a void *, which points to a newly allocated place in the heap that is large enough to hold a struct n.
Note that malloc() returns type void *, which is basically a pointer to any potential type, malloc() DOES NOT return type struct n * (a pointer to your declared struct type). void * has the special property of being able to be cast to any other type of pointer, and back again.
All together this means that your code doesn't actually work, since the first dereference of your struct n** would be a struct n, not a struct n*. If you tried to dereference twice, you would most likely get an invalid memory reference and crash.
The reason that your code can compile and run without crashing is because:
The compiler automatically casts void * to struct n **
You never attempt to actually dereference your pointer, which means you never attempt an invalid memory reference.
Simplify the problem and understanding may come:
int main()
{
struct n data;
struct n *pData = &data; // skipped in your version
struct n **ppData = &pData;
// struct n **ppData = &data; // Will not compile
// struct n **ppData = (struct n **)&data; // Casting but wrong!
return 0;
}
Because malloc() returns a void ptr, you are free to store the pointer into anything that is a pointer datatype. On your head if you put it into the wrong datatype...

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);
}

Pointers to pointers to structures

Hi have a function which takes the argument of a pointer, to a pointer to a struct. I'm having trouble accessing the members of my struct. Do struct pointers behave differently to pointers of other types, or am i just missing somethign essential?
struct mystr {
int num;
};
void fun(mystr **out) {
printf("%d",**out.num); <-- where the problem arises
}
No, 'struct pointers' (whatever you mean) work precisely the same way as pointers to other types.
You just need to recall operators precedence:
. structure member access
->structure member access through pointer
(...)
* indirection (dereference)
(...)
So your expression **out.num is interpreted as *(*(out.num)) and your (out.num) is not a pointer, hence applying an asterisk to it is an error.
You need to parenthesise appropriate part of the expression to force a non-default operators binding: (**out).num – dereference out twice first to get to a struct mystr variable, then access that variable's num member.
The -> operator serves as a shortcut for accessing a member of pointed stucture:
(ptr_expr)->member_name is equivalent to (*(ptr_expr)).member_name
so you can replace (**out).num with (*out)->num.
Possible to the solution to use this :
printf("%d",(*out)->num);
instead of
printf("%d",**out.num);
This is the way you should implement, here printf("%d",(*(*out)).num); will print 1.
#include<stdio.h>
#include<stdlib.h>
struct mystr{
int num;
};
void fun(struct mystr **out) {
printf("%d",(*(*out)).num);
}
int main()
{
struct mystr m;
struct mystr *p;
struct mystr **pp;
p=&m;
pp=&p;
m.num=1;
fun(pp);
return 0;
}
Here m is our structure, p is pointer to structure and pp is pointer to the pointer p.

What does the notation (((nodeptr) (bodyptr)) -> type) mean in C?

I came across a piece of code that looks like this, where nodeptr and bodyptr are pointers to a struct, and type is a member of the struct.
#define Type(x) (((nodeptr) (x))->type)
What does it mean to have two pointers next to each other in brackets? I get that the -> notation gets the member of the struct, but am not sure about the first part of the line. I'm fairly new to C and am trying to get my head around pointers!
It's a cast.
In this part, ((nodeptr)(bodyptr)), The pointer bodyptr is casted as pointer of type nodeptr, then it accesses the member type of the structure pointed to by bodyptr.
I.e.
void *GetStructPtr(void); //The function returns a pointer to void
typedef struct //This is our structure
{
float a;
int type;
} node;
type def node *nodeptr; //This is our pointer type
void my func(void)
{
void *bodyptr; //Here we have a generic void pointer
bodyptr = GetStructPtr(); //Assign to it the vallue returned from function
//In the next line we cast our void* to a pointer to a structure node
//and then access its member type.
((nodeptr)bodyptr)->type = 0;
}
In your case it has been inserted in a macro to make it easier to use.
It is cast. The pointer bodyptr is being casted to nodeptr and then type member accessed. This means that instead of accessing type member directly from bodyptr it is first converted to pointer of type nodeptr and only then accessed. It is useful e.g. when first pointer is just a pointer to raw memory, of type void * and you want to treat this memory as given type, maybe some struct.
Example:
struct e {
int a;
double b;
};
struct e foo { 1, 2.0 };
void *pFoo = &foo; // p points at foo now
// I know p is now address of object of type struct e
// and I want to get it's 'a' element BUT I can't
// do p->a, p is of void* type, yet I can do
int a = ((struct e*)(pFoo))->a;

Resources