A pointer to the array in a struct - arrays

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

Related

Using bsearch with an array inside a struct

I have the following struct definition
typedef struct {
char* name;
int address;
line_type_t type; /* an enum */
} label_t;
typedef struct {
int count;
int max;
label_t** head;
} label_registry_t;
I'm trying to search it like so:
int label_cmp(const void* v1, const void* v2) {
label_t* l1 = (label_t*) v1;
label_t* l2 = (label_t*) v2;
return strcmp(l1->name, l2->name);
}
label_t* registry_find(label_registry_t* registry, char* name) {
label_t** result;
label_t label;
label.name = name;
result = bsearch(&label, registry->head, registry->count, sizeof(label_t*), &label_cmp);
if (result == NULL) {
return NULL;
}
return *result;
}
It is not successful. When I debug in label_cmp, I see the first argument is the name I expect, but the second is jibbrish. Looking at addresses, I see that v2 is 0x804e008, while registry->head is shown as 0x804e018 (actually, the debugger shows registry->head as 0x804e008, but then under it *head as 0x804e018).
So I imagine this has to do with word alignment, but I can't find a way to pass the right address to bsearch. I tried registry->head + 0 and &registry->head[0].
So what is the right way to use bsearch here?
If you want to find an X, you pass to bsearch an array of X [1] and an address of an X, and your comparison function accepts two addresses of X. To recap:
If you want to find an int, you pass to bsearch an array of int and an address of an int, and your comparison function accepts two addresses of int.
If you want to find a struct, you pass to bsearch an array of struct and an address of a struct, and your comparison function accepts two addresses of struct.
If you want to find a pointer to struct, you pass to bsearch an array of pointers to struct and an address of a pointer to struct, and your comparison function accepts two addresses of pointer to struct.
Now what your code has is an array of pointers to struct, and address of a struct, and a comparison function that accepts two addresses of struct. This ain't gonna work. You need to harmonise the inputs.
--
[1] An address of its first element actually, but it is not important here.

C pointer to array in struct passed into function

I am trying to pass a pointer to an array, inside a structure into a callback function for an sqlite3 operation. Unfortunately the logic stemming from my understanding of pointers (obviously missing something) does not work.
Simplified, this is what I have:
typedef struct sqlCallbackData
{
int16_t data_array[128][32];
// There are other members here too...
} SqlCallbackData_t;
//===========================================================================================================
//===========================================================================================================
void sql_getData(uint8_t seq_num, uint8_t seq_bank, int16_t *data, char *name)
{
// 'data' above will be a pointer to a 2D array
//...
// Initialise struct members to be passed into callback...
SqlCallbackData_t paramStruct;
//Thows: error: incompatible types when assigning to type 'int16_t[128][32]' from type 'int16_t *'
paramStruct.data_array = data;// I know this isn't right...
//...
// Pointer to paramStruct passed into void pointer in callback...
if (sqlite3_exec(dbPtr, sql, callback, &paramStruct, &zErrMsg) != SQLITE_OK)
{
fprintf (stderr, "SQL error: %s\r\n", zErrMsg);
sqlite3_free(zErrMsg);
}
//...
}
//===========================================================================================================
//===========================================================================================================
// Callback function
static int load_callback(void *paramStruct, int argc, char **argv, char **azColName)
{
int i;
uint8_t value;
//...
// Just making the syntax below a bit mroe readable, as I access members a fair bit in this function
SqlCallbackData_t *params = ((SqlCallbackData_t *)paramStruct);
//...
// Data retreived from sql database...
params->data_array[0][0] = value;// <- What I'm trying to acheive...obviosuly not correct
return 0;
}
So I am aware of how pointers to array are passed into functions (explained here ), but I am getting confused as to how i assign this pointer to array into a structure, to be passed into a function (and then be accessed as an array again).
Going round in circles, so any help would be greatly appreciated:)
I am trying to pass a pointer to an array, inside a structure
for that you need to change struct like this,look at two dimensional array pointer
typedef struct sqlCallbackData
{
int16_t (*data_array)[32]; //2d array pointer
// There are other members here too...
} SqlCallbackData_t;
When you assign address to pointer...
void sql_getData(uint8_t seq_num, uint8_t seq_bank, int16_t (*data)[32], char *name)
{
// 'data' above will be a pointer to a 2D array
// Initialise struct members to be passed into callback...
SqlCallbackData_t paramStruct;
paramStruct.data_array = data;
Assuming the data is always large enough to fill the whole data_array:
memcpy(paramStruct.data_array, data, sizeof(paramStruct.data_array))
Otherwise, take care to copy as much data as you actually have instead of just sizeof(whole array).
Array declared like that is not a pointer, it's a part of the structure.
That structure is at least 8KB long.

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;

typedef, arrays and pointers in C

I am studying a code written in C language.
The following part isn't clear for me:
typedef uint8_t data_t[4][4];
typedef struct {
data_t *data;
...
} my_struct;
The thing that I don't understand is, what is the type of data?
Plus, I want to assign values to this variable.
For example, in the code there is:
my_struct st;
st.data = (int8_t *)array
where array is defined as int8_t *array.
I don't understand how this assignation works, could someone explain it clearly?
To finish, is it possible to assign values to my data_t variable without declaring it as a pointer in my structure?
The thing that I don't understand is, what is the type of data?
The type of data is a pointer to a two-dimensional array. That is uint8_t(*data)[4][4].
See C right-left rule for deciphering C declarations.
Plus, I want to assign values to this variable st.data = (int8_t *)array.
In this case array must have the same layout as uint8_t[4][4] array. Since arrays are contiguous in C, that array must have at least 4 * 4 elements of type int8_t.
The fact that you have to cast the array with (uint8_t*) first implies that array has a different type and that may cause trouble.
Note that this is a pointer assignment only, not an element-wise copy of array.
is it possible to assign values to my data_t variable without declaring it as a pointer in my structure?
It is possible if data is not a pointer, i.e. declare it as data_t data;. And then copy into it using memcpy.
This declaration
typedef uint8_t data_t[4][4];
declares name data_t as an alias for type uint8_t [4][4].
Thus in the structure definition
typedef struct {
data_t *data;
...
} my_struct;
member data is a pointer of type data_t * that is the same as uint8_t ( * )[4][4].
So it is a pointer to a two-dimensional array of pointers to objects of type `uint8_t
Arrays do not have the assignment operator. You have to copy elements of one array into another.
If for example you have another one-dimensional array of pointers like
uint8_t *array[4];
you could write
my_struct st;
st.data = malloc( sizeof( data_t ) );
memcpy( st.( *data )[0], array, 4 * sizeof( uint8_t * ) );
Take into account that as the data is a pointer you have at first to allocate memory where you are going to copy objects of type uint8_t *.

Assign value at pointer value from void pointer

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.

Resources