Reputation: 197
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
Upvotes: 0
Views: 1060
Reputation: 443
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
Upvotes: 1
Reputation: 11
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;
}
Upvotes: 1