Printing data in multiple structures

I work with four different frameworks, two of which are quite large. I have a function to write each value of each structure to a .txt file, but the code is very long and reliable. I'm looking for a way to print each value without having to hardcoding each one, but everything I've found so far in my research indicates that hardcoding is the only way, but I figured I'd check here before I give up completely ... Since it's standing 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 this has been going on for a while. (80 values) Is there an easier way to do this? If so, how do you do it?

+3


source to share


3 answers


The following solution defines union

which combines the actual struct

and its integral elements with an array of integral values ​​to "view" the structure elements as array elements available via subscription.

To make this preservation, we need to control the alignment, since the compiler can add padding between data items. This would then allow the "array" to point to invalid memory and introduce undefined behavior.

I suggest using #pragma pack(n)

to control alignment. Note that the code can also work without this binding, but a problem may arise if data items of a different type are entered before or after the "whole block" (this would also require an "array view" offset, but that is not shown here).



The surrounding union must ensure that the array and structure are correctly aligned; otherwise, casting from structure to array may result in undefined behavior.

I know it is #pragma pack

not portable and that it affects memory layout and probably speed. However, it should work on most compilers, and I think this is necessary for alignment control 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;
}

      

+2


source


In C11, you can rewrite yours struct

with unnamed structs and union fields.

Something like that:



#include <stdio.h>

struct dir_t
{
    int pos;
    int neg;
};

struct cam_temp_t
{
    dir_t x;
    dir_t y;
    dir_t z;
};

// it seems that you have only ints in your structure...
#define TOTAL_N_INTS 8

struct batty_t
{
    union
    {
        int data_[TOTAL_N_INTS];  
        struct
        {
            struct cam_temp_t camera_temperature;
            int               fpga;  // you get it...
            int               bat;
        }
    };
};

int main(void)
{
    struct batty_t example = {
        .camera_temperature = {
            .x = {3, 4},
            .y = {5, 6},
            .z = {7, 8}
        },
        .fpga = 1,
        .bat = 2
    };

    for (int i = 0; i < TOTAL_N_INTS; ++i )
    {
        printf("%4d", example.data_[i]);
    }
    return 0;
}

      

Of course, if you have different types, you should use different arrays.

+1


source


Accessing an array int

using struct

and vice versa, how this answer might be valid, maybe not. However, I'm not that sure now about using it with generic types. Leaving this as a wiki for anyone to add / change / remove.


The OP later noted that members are struct

not all int

. Oh good.


If all members and forever will int

...

Access to each member one at a time int

.

Incorrect code to illustrate the idea:

int print_int_struct(char *dest, size_t d_size, const void *st, size_t s_size) {
  if (s_size % sizeof(int) != 0) {
    return -1; // bad struct size
  }
  size_t n = s_size / sizeof(int);
  const char *delimiter = "";
  for (size_t i = 0; i < n; i++) {
    int d;
    memcpy(&d, st, sizeof d);
    st = (char*) st + sizeof(int);
    int len = snprintf(dest, d_size, "%s%d", delimiter, d);
    if (len < 0 || (size_t) len >= d_size) {
      return -1; // out of room
    }
    dest += len;
    d_size -= len;
    delimiter = " ";
  }
  return 0;
}
struct s1 {
  int VBUS_voltage_mV;
  int temp_internal_degC;
  int status;
  ...
};

struct s1 st = ...;
char buf[1024];
print_int_struct(buf, sizeof buf, &st, sizeof st);
puts(buf);

      

+1


source







All Articles