How to use the double pointer structure correctly - c

Below is the code, I'm so puzzled of how to use that double pointer int struct _AReport and struct _BReport.
My system is running on a Embedded computer, I use VS to debug this parts.
My system is composed of 1 struct _AReport, 17 struct _BReport and 16 struct _CReport on the whole.
The goal is that struct _AReport will contain all the informations.
I'm poor at English, thanks for being patient.
#include "stdafx.h"
typedef struct _AReport AReport;
typedef struct _BReport BReport;
typedef struct _CReport CReport;
typedef struct _AData AData;
typedef struct _BData BData;
typedef struct _CData CData;
typedef struct _ABCDatas ABCDatas;
struct _AReport
{
AData *adata;
BReport **breport;
};
struct _BReport
{
int _b;
BData *bdata;
CReport **creport;
};
struct _CReport
{
int _c;
CData *cdata;
};
int main()
{
int i = 0;
AReport Ar;
//BReport Br_dyadic[17][16] = { 0 };
BReport Br[17];
BReport *Br_Pointer = Br;
Ar.breport = &(Br_Pointer);
for (i = 0; i < 17; i++)
{
Br[i]._b = i + 1;
}
(Ar.breport[0])->_b = 99;
(Ar.breport[0] + 1)->_b = 99;
return 0;
}

If your question is does this problem require pointers to pointers, the answer is no: pointer arithmetics allow a single pointer to access all elements of a 1D array.
But if your question is does the last lines correctly access the elements of Br, then the answer it yes. Here is what actually happens:
Ar.breport is a pointer to a pointer to the first element of array Br (from BReport *Br_Pointer = Br; Ar.breport = &(Br_Pointer);, BrPointer being a pointer to first element of Br)
Ar.breport[0] is by definition the same as *(Ar.breport) => it is a pointer to the first element of Br
so Ar.breport[0] + 1 is by pointer arithmetics a pointer to the second element of Br
It is then legal to use those 2 pointers to dereference them and access the _b member of the BReport they point to.
You could make sure of that by simply adding:
printf("%d - %d - %d\n", Br[0]._b, Br[1]._b, Br[2]._b);
just before the return 0; (of after adding #include <stdio.h>...) and that should print 99 - 99 - 2

Related

assign a nested structure pointer to a nested structure

I've one solid structure and another structure with pointers. The purpose of program is to assign: solid structure to structure with pointers and access each solid structure member using other structure pointer.
I've problem statement: as two structure member as not symmetric, when i assign solid structure address to structure with pointers, member pointer initialization go bad and crash the system.
Does anyone have any approach to find a solution for this problem in an optimized way?
----------------------------------------------------------------------- program -----------------------------
#include <stdio.h>
#include <string.h>
#include <stddef.h>
/* ===================== Binding Structure ================================= */
typedef struct
{
char id;
}tmodel;
typedef struct
{
char id;
}tbrand;
typedef struct
{
char id;
}tcommercialRef;
typedef struct
{
char id;
}tserialnum;
typedef struct
{
tmodel *smodel;
tbrand *sbrand;
tcommercialRef *scommref;
tserialnum *sslnum;
}tmetadata;
typedef struct
{
tmetadata *smetadata;
}tlink;
typedef struct
{
tlink *slink;
}trefernce;
typedef struct
{
char id[10];
int ttl;
int tss;
trefernce *sref;
}telectrical;
/* ===================== Application Strucuture ==============================*/
void filldata(telectrical *elec);
typedef struct
{
tmodel smodel;
tbrand sbrand;
tcommercialRef scommref;
tserialnum sslnum;
}Ymetadata;
typedef struct
{
Ymetadata smetadata;
}slink;
typedef struct
{
slink glink;
}refernce;
typedef struct
{
char id[10];
int ttl;
int tss;
refernce grefernce;
}gtelectrical;
//solid strucutre object
gtelectrical obj;
//structure pointer object
telectrical *elec = {0};
/* =============================== main.c =================================== */
int main()
{
printf("test");
//static void **p = (void *)&elec;
obj.tss = 55;
obj.ttl = 100;
obj.grefernce.glink.smetadata.smodel.id = 5;
obj.grefernce.glink.smetadata.sbrand.id = 6;
obj.grefernce.glink.smetadata.scommref.id = 7;
obj.grefernce.glink.smetadata.sslnum.id = 8;
elec = (telectrical *)&obj;
//elec structure -> sref pointer goes bad as it's not same type as "grefernce"
//*p = (void *)&obj;
//static long x = (long) offsetof( telectrical, sref);
//(long) offsetof(struct telectrical, sref);
//*(*p + x) = obj.grefernce.glink.smetadata.;
elec->id[0] = 0;
elec->id[1] = 1;
elec->id[2] = 2;
elec->ttl = 5;
elec->tss = 10;
elec->sref->slink->smetadata->sslnum->id = 4;
elec->sref->slink->smetadata->sbrand->id = 1;
elec->sref->slink->smetadata->scommref->id = 2;
elec->sref->slink->smetadata->smodel->id = 3;
//filldata(elec);
printf("------");
printf("%d\n",elec->sref->slink->smetadata->sslnum->id);
printf("%d\n",elec->sref->slink->smetadata->sbrand->id);
printf("%d\n",elec->sref->slink->smetadata->scommref->id);
printf("%d\n",elec->sref->slink->smetadata->smodel->id);
return 0;
}
/* //////////////////////////////////////// user scope ////////////////////////////// */
void filldata(telectrical *pelec)
{
pelec->id[0] = 0;
pelec->id[1] = 1;
pelec->id[2] = 2;
pelec->ttl = 5;
pelec->tss = 10;
//pelec->sref->slink->smetadata->sslnum->id = 4;
//pelec->sref->slink->smetadata->sbrand->id = 1;
//pelec->sref->slink->smetadata->scommref->id = 2;
//pelec->sref->slink->smetadata->smodel->id = 3;
}
You are not assigning memory for the pointers to other struct present inside another struct. Here is something which might help you in multi-level memory allocation and assignment:
#include<stdio.h>
#include<stdlib.h>
typedef struct A
{
int i;
}A_Node;
typedef struct B
{
A_Node *A_ptr;
}B_Node;
typedef struct C
{
B_Node *B_ptr;
}C_Node;
int main(void)
{
//ACCESSING-MANIPULATING A USING B
B_Node B_obj;
B_obj.A_ptr=malloc(sizeof(*(B_obj.A_ptr)));
(B_obj.A_ptr)->i=192;
A_Node A_obj=*(B_obj.A_ptr); //For checking if the allocation is successful and good
printf("%d\n",A_obj.i);
//ACCESSING-MANIPULATING A USING C
C_Node C_obj;
C_obj.B_ptr=malloc(sizeof(*(C_obj.B_ptr))); //allocating space for struct of B using C object
(C_obj.B_ptr)->A_ptr = malloc(sizeof(*((C_obj.B_ptr)->A_ptr))); //allocating space for struct of A using B Struct for which space was allocated in previous step by C struct
((C_obj.B_ptr)->A_ptr)->i=876;
A_obj=*((C_obj.B_ptr)->A_ptr); //For checking if the allocation is successful and good
printf("%d\n",A_obj.i);
return 0;
}
Read the code and ask if there are any doubts, in the similar way this multi-level struct-inside-struct can be created (though it would be ugly).

Realloc struct with ** pointer to another struct

How can I realloc a double pointer inside a struct to another struct?
The double pointer is not used as a 2d array.
Code example.
struct x_tag {
int a;
int b;
};
typedef struct x_tag x_t;
struct y_tag {
x_t ** p;
int n;
};
typedef struct y_tag y_t;
/////////////////////////////////
y_t * d = malloc(sizeof(*d));
x_t * c = malloc(sizeof(*c));
d->p = &c;
/////////////////////////////
d->p = realloc(d->p, d->n*sizeof(x_t)); doesn't work.
d->p[0] = realloc(d->p[0], d->n*sizeof(x_t)); doesn't work.
*(d->p) = realloc(*(d->p), d->n*sizeof(x_t)); doesn't work.
*(d->p)[0] = realloc(*(d->p)[0], d->n*sizeof(x_t)); doesn't work.
Any ideas?
///////More info////////
The struct was not defined by me, but unfortunately I need to use this. Double pointers does not make sense to me either in this case.
The main idea is to change the size of (y_t **p) dinamically. The program should change the double pointer size every time another struct (x_t) is added.
|*d|--->|struct y_t|--->|**p|--->|*p|--->|struct x_t [0]|
|----->n |----->|struct x_t [1]|
|----->|struct x_t [2]|
I change the code to:
y_t * d = malloc(sizeof(*d));
d->p = malloc(sizeof(*d->p));
d->p[0] = malloc(sizeof(*d->p[0]));
Not working.

Assign value to field in array of nested structs

I have a function test that accepts a pointer to a structure. How can I set the value of a field in a structure in the nested structure array? The structures are created and deleted elsewhere, I just want to set the value.
typedef struct {
int a;
} inner_struct_t;
typedef struct {
int b;
inner_struct_t innerStructsArr[];
} outer_struct_t;
void test(outer_struct_t *outerStruct);
void test(outer_struct_t *outerStruct) {
outerStruct->b = 123; // set a value in the outer struct
(outerStruct->innerStructsArr)[0].a = 456; // but this DOESN'T work
}
Here's a complete example that should work for you:
#include <stdio.h>
#include <malloc.h>
typedef struct {
int a;
} inner_struct_t;
typedef struct {
int b;
inner_struct_t *innerStructsArr;
} outer_struct_t;
void test(outer_struct_t *outerStruct, int n) {
outerStruct->b = 123; // set a value in the outer struct
outerStruct->innerStructsArr = malloc(sizeof(inner_struct_t) * n); // Allocate space
outerStruct->innerStructsArr[0].a = 456; // Assign a value
}
int main (int argc, char *argv[]) {
outer_struct_t s;
test(&s, 1);
printf("b=%d, inner[0]=%d\n", s.b, s.innerStructsArr[0].a);
free(s.innerStructsArr);
return 0;
}
When you have a structure with a flexible array member (FAM) in it, you need to allocate the space for the array at the same time that you allocate the space for the structure.
ISO/IEC 9899:2011 §6.7.2.1 Structure and union specifiers
¶18 As a special case, the last element of a structure with more than one named member may
have an incomplete array type; this is called a flexible array member. In most situations,
the flexible array member is ignored. In particular, the size of the structure is as if the
flexible array member were omitted except that it may have more trailing padding than
the omission would imply. However, when a . (or ->) operator has a left operand that is
(a pointer to) a structure with a flexible array member and the right operand names that
member, it behaves as if that member were replaced with the longest array (with the same
element type) that would not make the structure larger than the object being accessed; the
offset of the array shall remain that of the flexible array member, even if this would differ
from that of the replacement array. If this array would have no elements, it behaves as if
it had one element but the behavior is undefined if any attempt is made to access that
element or to generate a pointer one past it.
Given:
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int a;
} inner_struct_t;
typedef struct
{
int b;
inner_struct_t innerStructsArr[];
} outer_struct_t;
static void test(outer_struct_t *outerStruct)
{
outerStruct->b = 123;
outerStruct->innerStructsArr[0].a = 456;
}
int main(void)
{
outer_struct_t *os = malloc(sizeof(*os) + 4 * sizeof(os->innerStructsArr[0]));
for (int i = 0; i < 4; i++)
os->innerStructsArr[i].a = 10 * i;
test(os);
printf(" b = %d\n", os->b);
for (int i = 0; i < 4; i++)
printf("[%d].a = %d\n", i, os->innerStructsArr[i].a);
free(os);
return 0;
}
Sample output:
b = 123
[0].a = 456
[1].a = 10
[2].a = 20
[3].a = 30

How to typecast void pointer based on condition?

To explain more, I have two structures-'first' and 'second' having common variables 'jack' and 'jill'. I want to print jack via a pointer based on if-else condition.
I understand at the time of printing I have to typecast the void pointer. But whether the pointer points to struct a or b is decided on run time.
It is a basic C code. How to overcome this?
Code
#include <stdio.h>
int main(void)
{
typedef struct one
{
int jack;
float jill;
}a;
typedef struct two
{
int jack;
float jill;
char something;
int something1;
}b;
a first;
b second;
void *z;
if(1)
{
a* z;
z = &first;
printf("First one");
}
else
{
b* z;
z = &second;
printf("Second one");
}
printf("%d\n", z->jack);
return 0;
}
Error
prog.c:36:17: warning: dereferencing 'void *' pointer printf("%d\n", z->jack); prog.c:36:17: error: request for member 'jack' in something not a structure or union
You get a compiler warning since the compiler does not understand z->jack since z is a void * (note that the declarations a* z and b* z are not valid outside the scope of the if and else block).
To overcome this you can use a function printJack as shown in the following listing:
#include <stdio.h>
typedef struct one
{
int jack;
float jill;
}a;
typedef struct two
{
int jack;
float jill;
char something;
int something1;
}b;
void printJack(void *pStruct, int type)
{
switch (type)
{
case 1:
printf("jack: %d\n", ((a *)pStruct)->jack);
break;
default:
printf("jack: %d\n", ((b *)pStruct)->jack);
break;
}
}
/*
** main
*/
int main(void)
{
a first;
b second;
void *z;
first.jack = 5;
second.jack = 4892;
printJack(&first, 1);
printJack(&second, 0);
z = &first;
printJack(z, 1);
return (0);
}
I've written code like this often and experienced a lot of trouble with it. Not at the time of implementing, since you are knowing what you are typing at that moment but let's say a few years later if you need to extend your code. You will miss a few places where you cast from void * to a * or b * and you'll spend a lot of time debugging what's going on...
Now I'm writing things like this in the following way:
#include <stdio.h>
typedef struct header
{
int jack;
float jill;
} h;
typedef struct one
{
struct header header;
/* what ever you like */
}a;
typedef struct two
{
struct header header;
char something;
int something1;
/* and even more... */
}b;
void printJack(void *pStruct)
{
printf("jack: %d\n", ((struct header *)pStruct)->jack);
}
/*
** main
*/
int main(void)
{
a first;
b second;
void *z;
first.header.jack = 5;
second.header.jack = 4892;
printJack(&first);
printJack(&second);
v = &first;
printJack(v);
return (0);
}
As you've noticed I have declared a new struct header which covers the the common parts of struct one and struct two. Instead of casting the void * to either a * or b * a "common" cast to struct header * (or h *) is done.
By doing so you can easily extend the "common attribtues" of the structs or you can implement further structs using this header and function printJack still will work. Additionally there is no need for attribute type anymore making is easier to call printJack. You can even change the type of jack without needing to change it in various places within your code.
But remember that struct header needs to be the first element of the structs you use this mechanism. Otherwise you will end up with a few surprises since you are using memory which does not contain the data of the struct header...

invalid type argument of ‘->’ (have ‘struct coada’)

I am trying to create a list of threads that would be locked and executed in the order of the list. here is the code( it's a busy wait simulation I have for a course)
# include <stdio.h>
# include<pthread.h>
# include<stdlib.h>
# define NKIDS 10
pthread_mutex_t mutx;
struct kidrec {
int data;
pthread_t id;
};
struct coada {
struct kidrec th;
struct coada *next;
};
void *copilfunc(void*p)
{
int *ip=(int*)p;
int tmp;
int v;
pthread_mutex_lock(&mutx);
tmp=v; v=*ip;
printf(" We are at thread %d \n",v);
pthread_mutex_unlock(&mutx);
}
int main(){
struct kidrec kids[NKIDS];
struct coada c[NKIDS];
int m;
for(m=0;m<NKIDS;m++){
kids[m].data=m;
pthread_create(&kids[m].id,NULL,copilfunc,&kids[m].data);
c[m].th=kids[m];
if(m>0) c[m-1]->next=c[m];
if(m==NKIDS) c[NKIDS]->next=c[0];
}
for(m=0;m<NKIDS;m++)
pthread_join(c[m].th.id,NULL);
}
You are trying to access an attribute on an array of a struct using -> which is an access operator used for pointers (non-arrays)...
Try using
c[i].next = &c[j]
instead of
c[i]->next = c[j]
;)
The variable c[] is an array of struct coada, not struct coada *.
So the expression c[m-1] is a struct coada, and you access its fields with ..
Thus, it should be:
c[m - 1].next = &c[m];
It doesn't matter that next is a pointer, the period is for accessing the struct-typed value on its left. Also note that you need to take the address of the array element, thus the & on the right.

Resources