Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Printing the data in multiple structs

Tags:

c

file

struct

I'm working with four differest structs, two of which are quite large. I have a function to write each value of each struct to a .txt file, but the code is very long and robust. I'm looking for a way of printing out each value without having to hard code each in, but everything I've found so far in my research indicates that hardcoding is the only way, but I figured I'd check on here before I give up completely. As it stands right now, my code looks like this:

char text[416];
    snprintf(text, 416, 
        "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d", 
        epsy.VBUS_voltage_mV,
        epsy.temp_internal_degC,
        epsy.status,
        batty.Z_pos_Camera_Temperature,
        batty.Z_neg_Camera_Temperature,
        batty.Y_pos_Camera_Temperature,
        batty.Y_neg_Camera_Temperature,
        batty.X_pos_Camera_Temperature,
        batty.FPGA_Temp_1,
        batty.FPGA_Temp_2,
        batty.Rx_Hinge_Temperature,
        batty.Bat_1_Vbat,
        batty.Bat_1_Ichg,
        batty.Bat_1_Idch,
        batty.Bat_1_MCU_Temp,
        batty.Bat_1_Temp_Therm,
        batty.Bat_1_Status,
        batty.Bat_2_Vbat,
        batty.Bat_2_Ichg,
        batty.Bat_2_Idch,
        batty.Bat_2_MCU_Temp,

... and it goes on for a while. (80 values) Is there a simpler way of doing this? If so, how do I do it?

like image 246
Connor Olsen Avatar asked Jan 23 '26 14:01

Connor Olsen


1 Answers

The following solution defines a union that combines the actual struct with it's integral members with an array of integral values in order to "view" the struct members as array elements accessible through subscription.

To make this save, we need to control the alignment, since the compiler might add padding between the data members. This would then let the "array-view" point to invalid memory and introduce undefined behaviour.

I suggest to use #pragma pack(n) to control the alignment. Note that the code may also work without this alignment thing, yet it might get a problem if data members of other type are introduced before or after the "integral block" (This would also require to offset the "array-view", but that's not shown here).

The surrounding union is required to guarantee that the array and the struct are actually aligned correctly; otherwise, a cast from a struct to an array might introduce undefined behaviour.

I'm aware that #pragma pack is not portable and that it affects the memory layout and probably speed. Yet it is supposed to work on most compilers, and I think it is needed for controlling alignment in order to avoid UB:

#pragma pack(4)     /* set alignment to 4 byte boundary */

#define nrOfMyPackedDataElements 3

union MyPackedData {

    struct {
        int32_t firstInt;
        int32_t secondInt;
        int32_t thirdInt;
    } data;

    int32_t array[nrOfMyPackedDataElements];
};

#pragma pack()      /* reset alignment to compiler default */

int main() {

    union MyPackedData data;
    data.data.firstInt = 10;
    data.data.secondInt = 20;
    data.data.thirdInt = 30;

    for (int i=0; i < nrOfMyPackedDataElements; i++) {
        printf("%d ",data.array[i]);
    }

    return 0;
}
like image 83
Stephan Lechner Avatar answered Jan 26 '26 07:01

Stephan Lechner



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!