Stringize loopcounter to reference members of C struct - c

I have two structs that appears like:
typedef unsigned char byte;
struct my_struct_2 {
int type;
int length; //will be 2 in this case
byte value1; //MSB
byte value2; //LSB
}
struct my_struct_4 {
int type;
int length; //will be 4 in this case
byte value1; //MSB
byte value2;
byte value3;
byte value4; //LSB
}
I want to loop through the "value" members in the struct based on "length" to concatenate the byte values into one number. I am wondering if it is possible to use some sort of stringizing so that I can construct a for loop with a structure similar to this:
int value = 0;
for( int i = 1; i <= length; i++)
{
value = value << 8;
value = value & my_struct.value#i#;
}
I want to take advantage of the fact that the structs members are sequentially named.
I know that I can accomplish this task by using a pointer to the first value and incrementing the pointer. I am trying to familiarize myself more with stringizing so please refrain from a pointer like solution. Thanks!

There is no way to loop through struct fields by constructing names like that. Once a C program has been compiled, any information about names is gone (ignoring information for the debugger); it's all offsets hard-coded into the machine code.
With some C preprocessor abuse you can get something a bit like looping on names, but it's not pretty and definitely not recommended unless you're just doing it for the challenge of doing it.

Related

Get the index of an element declared in a struct

I'd like to associate each element of my struct (or something else, may not be possible with a struct) with an incrementing index, kind of like an enum but associate with value fields.
Let's say that I have this data struct :
typedef struct
{
int8_t value_at_index0; // start with index 0 for this field
int8_t value_at_index1; // then index = 1, etc
int8_t value_at_index2;
int8_t value_at_index3;
int8_t value_at_index4;
} data;
I want to get the index of a field, and the index should mirror the position where the field was declared in the struct.
EDIT: My problem is that I want to write values in an external memory, but I don't want to figure at which index is the value. For example I'd like to do that: write(index.value_at_index2, data.value_at_index2)
Thanks
Ok im assuming you have a badly written code and don't wanna fix it or its a very specific problem
Although i would just use an array or allocate some memory for it, I haven't read the manual but i remember in a year ago that structs are always written as a block(ie they aren't fragmented unlike memory allocation) and although this is not correct behavior to work with structs like this i did a test and it worked
Use __attribute__((packed, aligned(1))), this makes the padding 1, meaning that no blank space bytes will be added, that is if you have a single byte element it wont add 3 more blank ones to fill the gap.
This doesn't mean that it will shorten everything to one and this stops working as soon as you factor in elements of different sizes as adding one when its going through a 4 bytes integer will cause unexpected behaviour
typedef struct __attribute__((packed, aligned(1))) //like so
{
int8_t value_at_index0; // start with index 0 for this field
int8_t value_at_index1; // then index = 1, etc
int8_t value_at_index2;
int8_t value_at_index3;
int8_t value_at_index4;
} data;
int main(int argc, char **argv){
data data;
int8_t *hey=NULL;
data.value_at_index0=5;
data.value_at_index1=3;
data.value_at_index2=2;
data.value_at_index3=5;
data.value_at_index4=10;
size_t i;
hey = &data;
for (i = 0; i < 5; i++){
printf("hey its working %d", *hey);
hey+=1;
}
//letsee(5, data);
return 0;
}
Now this is not correct behavior, superficially by your question i would just advise you to stick with memory allocation since it allows for dynamic sizes and even if you want a static size, you could just use arrays.
If you want an even sketchier version of above in the most recent C compilers there is a few tricks to make it dynamic. Although i will tell you that you're gonna have a bunch of memory leaks, core dumps, and unexpected behavior
TL;DR This is not correct behavior and I'm just posting this in case that you can't change the code and you must use structs
Now for the clean version i read in the question that you are going to write a struct assuming that the struct is basic and you just wanna write every static element in it you can easily just do
FILE *fp;
if ((fp = fopen("lets.txt", "w")) == NULL){
return 1;
}
fwrite(&data, sizeof(data), 1, fp);
if (fclose(fp) != 0){
return 1;
}
since when you place a struct in the first parameter, and provide the size of it it will just write every element inside the struct, this also applies to pointers although there you have to specify the size of each element in the size param and the number of elements in the next param.
Again this is assuming all your elements are well defined and static, since structs have a lot of flag's
You should consider using arrays/pointers for this purpose. To make this work you need to make sure that all values are the same type and temporary removing memory padding for that struct. The following code illustrates how it is being done.
/*Remove struct padding*/
#pragma pack(push, 1)
typedef struct
{
int8_t a;
int8_t b;
int8_t c;
int8_t d;
} data;
/*Recover struct padding, some structs from other libraries malfunction from not using struct pudding.*/
#pragma pack(pop)
int main()
{
/*Define a clean data structure*/
data tmp = { 0x00, 0x00, 0x00, 0x00 };
((int8_t *)&tmp)[0] = 0x01; /*data.a = 0x01*/
((int8_t *)&tmp)[1] = 0x03; /*data.b = 0x03*/
((int8_t *)&tmp)[2] = 0x05; /*data.c = 0x05*/
((int8_t *)&tmp)[3] = 0x07; /*data.d = 0x07*/
return 0;
}

How to manipulate structure members using bitwise operations?

For example, for a structure:
struct name{
int a;
char b;
float c;
}g;
g.b='X';
Now I would like to access structure member b using bitwise operators(<<,>> etc.) and change it to 'A'.
Is it possible to access structure members using such operators??
Bitwise operations on struct's doesn't make to much sense because of padding and more importantly it's just killing the purpose of having a struct in the first place. Bitwise operation are as the name said to operate on bit's in variable. Struct variables usually (if they're not packed) will be padded so until you pack them you wouldn't have guarantee where they are to access them but if you want to ask if you can, yes you can, but you would have to cast struct g to let's say 32 bit value then if two variables would be in this space you could use bit operation on this casted value. If it's necessary you can create union from your struct and have raw variable as one union part, and structure as the other option, then you can manipulate bitwise on raw variable.
You can change the data by getting offset of b. I know, this code does not look good.But it serve your purpose.
#include <stdio.h>
struct name
{
int a;
char b;
float c;
}g;
int main()
{
g.b='X';
int y=0;
int offset = &((struct name *)NULL)->b; // Find Offset of b
char *p = (char *)&g;
int i=0;
for(i=0;i<offset;i++)
{
++p;
}
*p=*p|(1<<0);
// *p = 'A';
printf("........%c\n",g.b);
}
there's a way, you have to copy the structure content into a variable (size of your struct), then manipulate the variable and finally copy the variable content back into the struct using memset.

defining structure variable during declaration

I have been trying something in structures in C.
struct val{
unsigned int a : 1 ;
}store[100] ;
Now I want to initialize all the array members value to 1. That is, I want all the array members to have their variable a assigned to 1. I can use a loop for that but how can I do this during the declaration?
struct val
{
unsigned int a=1 : 1 ;
}store[100];
How can i achieve this? The above syntax is coming out to be wrong in code::blocks.
struct val
{
unsigned int a : 1;
}store[100];
I initially thought that what you were doing was a bitfield initialization. Further research though suggested I am wrong, and that you are trying to use gcc's designated initializers. What you want to do, is not possible that way. I found another way in your code that you can do it, though:
typedef struct {
unsigned int a;
} val;
then, where you want to initialize the array, you will do something like that:
val values[100] = {[0].a = 1};
This works by exploiting this behavior of gcc:
If the same field is initialized multiple times, it has the value from the last initialization. If any such overridden initialization has side-effect, it is unspecified whether the side-effect happens or not. Currently, GCC discards them and issues a warning.
My Test Program follows:
#include <stdio.h>
struct val {
unsigned int a;
};
int
main (void)
{
struct val value[100] = {[0].a = 1};
printf ("A random val's value is %d\n", value[40].a);
return 0;
}
Compiles and works cleanly on my GCC 4.9.1.
It's not possible.
You can use a loop, or, if by any chance you want to initialize all struct's data members to a specific value, you can also use memset:
struct val {
unsigned int a : 1 ;
} store[N];
memset(store, value, N * sizeof(struct val));
Before declaring a struct variable you can't initialize its member. Initialization can be done as
struct val{
unsigned int a : 1;
}store[100] = {[0].a = 1} ; // Designated initializer
but it will initialize a member of other elements of store to 0. To initialize member a of all elements of store you need a loop.

Kind of polymorphism in C

I'm writing a C program in which I define two types:
typedef struct {
uint8_t array[32];
/* struct A's members */
...
} A;
typedef struct {
uint8_t array[32];
/* struct B's members, different from A's */
...
} B;
Now I would like to build a data structure which is capable of managing both types without having to write one for type A and one for type B, assuming that both have a uint8_t [32] as their first member.
I read how to implement a sort of polymorphism in C here and I also read here that the order of struct members is guaranteed to be kept by the compiler as written by the programmer.
I came up with the following idea, what if I define the following structure:
typedef struct {
uint8_t array[32];
} Element;
and define a data structure which only deals with data that have type Element? Would it be safe to do something like:
void f(Element * e){
int i;
for(i = 0; i < 32; i++) do_something(e->array[i]);
}
...
A a;
B b;
...
f(((Element *)&a));
...
f(((Element *)&b));
At a first glance it looks unclean, but I was wondering whether there are any guarantees that it will not break?
If array is always the first in your struct, you can simply access it by casting pointers. There is no need for a struct Element. You data structure can store void pointers.
typedef struct {
char array[32];
} A;
typedef struct {
void* elements;
size_t elementSize;
size_t num;
} Vector;
char* getArrayPtr(Vector* v, int i) {
return (char*)(v->elements) + v->elementSize*i;
}
int main()
{
A* pa = malloc(10*sizeof(A));
pa[3].array[0] = 's';
Vector v;
v.elements = pa;
v.num = 10;
v.elementSize = sizeof(A);
printf("%s\n", getArrayPtr(&v, 3));
}
but why not have a function that works with the array directly
void f(uint8_t array[32]){
int i;
for(i = 0; i < 32; i++) do_something(array[i]);
}
and call it like this
f(a.array)
f(b.array)
polymorphism makes sense when you want to kepp
a and b in a container of some sorts
and you want to iterate over them but you dont want to care that they are different types.
This should work fine if you, you know, don't make any mistakes. A pointer to the A struct can be cast to a pointer to the element struct, and so long as they have a common prefix, access to the common members will work just fine.
A pointer to the A struct, which is then cast to a pointer to the element struct can also be cast back to a pointer to the A struct without any problems. If element struct was not originally an A struct, then casting the pointer back to A will be undefined behavior. And this you will need to manage manually.
One gotcha (that I've run into) is, gcc will also allow you to cast the struct back and forth (not just pointer to struct) and this is not supported by the C standard. It will appear to work fine until your (my) friend tries to port the code to a different compiler (suncc) at which point it will break. Or rather, it won't even compile.

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