pointer to array inside structure - c

I am trying to assign an int pointer to an int array which is a member of a structre.
The structure is a member of another structure, which happens to be an array of structures. And this array of structures happens to be a member of another structure. And this last structure happens to be an element of an array of structures.
typedef struct s_ptxRowProperties
{
int lastPlotValue[134];
} ptxRowProperties;
typedef struct s_ptxRow
{
ptxRowProperties PtxRowProperties;
} ptxRow;
typedef struct s_workSpace
{
ptxRow PtxRow[100];
} workSpace;
Edit:
I allocate 1 of these behemoths like this:
WorkSpace[n] = (workSpace *) calloc(1, sizeof(workSpace));
I have tried the following incantations, to no avail:
int *x= &(WorkSpace[i]->PtxRow[ptxRowIndex].PtxRowProperties.lastPlotValue)[0];
int *x= (&WorkSpace[i]->PtxRow[ptxRowIndex].PtxRowProperties.lastPlotValue)[0];
int *x= &(WorkSpace[i]->PtxRow[ptxRowIndex].PtxRowProperties->lastPlotValue)[0];
int *x= WorkSpace[i]->PtxRow[ptxRowIndex].PtxRowProperties.lastPlotValue;
int *x= *(WorkSpace[i]->PtxRow[ptxRowIndex].PtxRowProperties.lastPlotValue);
int *x= (*WorkSpace[i]->PtxRow[ptxRowIndex].PtxRowProperties->lastPlotValue);
I believe the hypothetical million monkeys in a room for 100 years will have composed Hamlet before they can create the correct form for this. Any ideas?

You probably want
int *x= &(WorkSpace[i]->PtxRow[ptxRowIndex].PtxRowProperties.lastPlotValue[0]);
This assumes that WorkSpace[i]->PtxRow[ptxRowIndex].PtxRowProperties.lastPlotValue[0] would reference the first element of the int array.

If WorkSpace[i]->PtxRow[ptxRowIndex].PtxRowProperties.lastPlotValue is the value you are interested in, than one would use & to get its address:
int *x = &WorkSpace[i]->PtxRow[ptxRowIndex].PtxRowProperties.lastPlotValue;

Related

Initiliazing int array with pointer type variable

I have the following code.
FlowNProcess f1[3];
int f1resources[2]={-1,0};
f1[1].resoures =f1resources;
typedef struct FlowNProcess
{
int id;
int tt;
int wt;
Requirement *requirement;
int *resoures;
char *state;
} FlowNProcess;
Here since the resources is an int* so, I am first creating an array of size 2 and then
assigning the pointer to it. Is there a better way to achieve the same, maybe a one-liner

Can you create an array of Structure inside of another structure in C language?

Aim : To create a structure of element having certain properties. Then utilize that structure type by creating it's array in another structure.
struct Element
{
int i;
int j;
int x;
};
struct Sparse
{
int r;
int c;
int n;
struct Element *ele;
ele = (struct Element *)malloc(n*sizeof(struct Element));
};
What I wish to know is that which part of the code am I not allowed to write while creating a structure.
The common way to do this is:
struct Element
{
int i;
int j;
int x;
};
struct Sparse
{
int r;
int c;
int n;
struct Element ele[0]; // Make a zero length array
};
struct Sparse* MakeNewSparse(size_t num_ele)
{
struct Sparse* sparse = malloc(sizeof(*sparse) + num_ele*sizeof(struct Element));
return sparse;
}
This works because accessing off the end of a zero-length array is totally legal in C, provided you have allocated memory there.
In this example, we allocate enough space for the struct Sparse, and then enough more contiguous space for the array of struct Element.
After that, accessing element sparse->ele[5] is totally legal.
The line
ele = (struct Element *)malloc(n*sizeof(struct Element));
should not be part of the struct definition - that's something you do at runtime, along these lines:
struct Sparse s; // create new struct Sparse instance
s.n = get_some_size();
s.ele = malloc( s.n * sizeof *s.ele ); // no need for cast
struct in c is syntactically similar with types like int, char, etc. The definition of a struct is for compiler to know how to use variable declared with that struct such as struct Sparse var;. So the definition of a struct is not actually the code itself. It will be used at compile time.
However, malloc() is a function, which will be used at runtime, so it is nonsense to put malloc() in your struct definition.

How to find out the amount of elements in array created for a struct?

I created a certain struct and then I went on to create an array for the struct in the following manner:
struct members
{
char name[32];
intmax_t personalID;
}typedef struct members Member;
Member array_member[100];
Later on, I want to know how many elements there are in the array, according to some answers I have read, this should be enough
int nrofmembers = sizeof(array_member) / sizeof(array_member[0]);
But due to my experience, I know that this is not possible if the array itself is a parameter. So I tried this:
int nrofmembers = sizeof(*array_member) / sizeof(array_member[0]);
Unfortunately, this has turned out to be wrong. The value of nrofmembers after this is 1, but that's not true.
Any advice on how to do this?
If you have the pointer you cant use this simple compile time method. You need to pass the size of the array to the function
In C you always pass the pointer even if your declaration is ... foo(Member arr[]) or ... foo(Member arr[100])
struct members
{
char name[32];
intmax_t personalID;
}typedef struct members Member;
Member array_member[100];
int foo(Member *arr, size_t size)
{
/* .... */
}
int main()
{
/* correct */
foo(array_member, sizeof(array_member) / sizeof(array_member[0]));
printf("Hello World");
return 0;
}

Changing the size of struct after declared

I have a code contains this structure
struct mystruct{
int a;
int array[1];
};
Directly, after running the code
I mean I will not declare any variable of that structure,the user will enter a number, for example 6.
What I want is to know how I can change the size of that structure.
Like I declared on this form
struct mystruct{
int a;
int array[6];
};
Then I use normally, like this:
struct mystruct var;
//I do not want to add any code here, to appropriate new form
for(int i=0;i<6;i++)
var.array[i]=0;
The typical way to do something like this in straight C (as opposed to C++) is to have just a pointer member in the struct, to point to the array, and then another member of the struct to indicate the size. This generally requires users of the struct to malloc() the array as needed, and to also set the size member to match. Something like:
struct mystruct
{
int size;
int *array;
};
and:
struct mystruct var;
var.array = malloc(6 * sizeof(int));
var.size = 6;
for (int i = 0; i < var.size; i++)
var.array[i] = 0;
Another common paradigm is a linked list.
Of course, in C++ you could just use a std::vector<int>.
You cannot change the declaration of the struct but if it is a variable length array within a struct that you want you do have an option. Declare your struct as:
struct mystruct{
int a;
int array[0];
};
And then when you want to create an instance with n elements in the array do the following:
struct mystruct *a = malloc(sizeof(struct mystruct) + n * sizeof(int));
This will create a memory region large enough to hold the struct and an array of length n. You can then use the array just as you would any other array:
a->array[1] = 5;
(this example assumes the array has at least 2 elements)
To accomplish what you have in your code example you would want to do something like this:
struct mystruct *var = malloc(sizeof(struct mystruct) + 6 * sizeof(int));
for(int i=0;i<6;i++) {
var->array[i]=0;
}
You cannot change an already declared struct, but you can make a new one as you want by modifying the program. You can't change data structures used in the program on the fly while it is running.

array to structure casting

I have these three structures,
typedef struct serial_header {
int zigbeeMsgType;
int seqNumber;
int commandIdentifier;
int dest;
int src;
}serial_header_t;
typedef struct serial_packet {
serial_header_t header;
int data[];
} serial_packet_t;
and last one is
typedef struct readAttributePacket
{
int u8SourceEndPointId;
int u8DestinationEndPointId;
int u16ClusterId;
int bDirectionIsServerToClient;
int u8NumberOfAttributesInRequest;
int bIsManufacturerSpecific;
int u16ManufacturerCode;
int pu16AttributeRequestList[];
}readAttributePacket_t;
I am troubling with this code, i just want to cast the data[] array which reside in serial_packet_t into readAttributePacket_t structure.
I think the data[] should be
data[]={0x01,0x01,0x04,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x01};
I need to cast those data to readAttributePacket_t structure. But this below code showing wrong.
void main()
{
int a[]= {0x32,0x00,0x31,0x69,0x69,0x00,0x00,0x01,0x01,0x04,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x01};
int i;
readAttributePacket_t *p;
serial_packet_t *data;
data = (serial_packet_t*)&a;
for(i=0;i<20;i++){
printf(" %02x \n",a[i]);
}
p = (readAttributePacket_t *)&data->data;
printf("\nu8SourceEndPointId:%x \nu8DestinationEndPointId:%x \nu16ClusterId:%04x \nbDirectionIsServerToClient:%x \nu8NumberOfAttributesInRequest:%x \nbIsManufacturerSpecific:%x \nu16ManufacturerCode:%04x",p->u8SourceEndPointId,
p->u8DestinationEndPointId,
p->u16ClusterId,
p->bDirectionIsServerToClient,
p->u8NumberOfAttributesInRequest,
p->bIsManufacturerSpecific,
p->u16ManufacturerCode);
getch();
}
the output should be like
u8SourceEndPointId=01
u8DestinationEndPointId=01
u16ClusterId=0402
bDirectionIsServerToClient=00
u8NumberOfAttributesInRequest=02
bIsManufacturerSpecific=00
u16ManufacturerCode=0000
How could I get the pu16AttributeRequestList[] array into readAttributePacket_t structure, should like that,
pu16AttributeRequestList[0]=0000
pu16AttributeRequestList[1]=0001
You can't just cast an array to a structure because they're simply incompatible types. Due to memory alignment constraints, the compiler needs to insert padding between the fields of a structure, so the members are not located at the memory addresses you may expect. Solutions:
Portable but slower/harder to do manually (preferred): copy manually the fields of the structure to the array.
Shorter to write but GCC-specific: use the __attribute__((packed)) keyword to make GCC not introduce padding between struct fields.
Construct a union of 3 structs. all on equal memory space. then you dont even need to cast.
I think the only thing that you need to do in to remove the address operator from the casting statement.
data = (serial_packet_t*)a;
instead of
data = (serial_packet_t*)&a;
as far as I know, everything should work fine from here.

Resources