我正在处理四种不同的结构,其中两种非常大。我有一个函数将每个结构的每个值写入.txt文件,但代码非常长且健壮。我正在寻找一种打印出每个值的方法,而不必对每个值进行硬编码,但我在研究中发现的所有内容都表明硬编码是唯一的方法,但我认为我是在我完全放弃之前检查一下。就目前而言,我的代码如下所示:
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,
......它会持续一段时间。 (80个值) 有更简单的方法吗?如果是这样,我该怎么做?
答案 0 :(得分:2)
以下解决方案定义了一个union
,它将实际的struct
与其整数成员组合在一起,形成一系列整数值,以便"查看" struct members作为可通过订阅访问的数组元素。
要进行此保存,我们需要控制对齐,因为编译器可能会在数据成员之间添加填充。然后,这将使" array-view"指向无效的内存并引入未定义的行为。
我建议使用#pragma pack(n)
来控制对齐方式。请注意,代码也可以在没有这种对齐的情况下工作,但如果在"整数块"之前或之后引入其他类型的数据成员,则可能会出现问题。 (这也需要偏移"数组视图",但这里没有显示)。
周围的联合需要保证数组和结构实际上是正确对齐的;否则,从结构到数组的强制转换可能会引入未定义的行为。
我知道#pragma pack
不可移植,它会影响内存布局,可能会影响速度。然而它应该适用于大多数编译器,我认为需要控制对齐以避免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;
}
答案 1 :(得分:1)
在C11中,您可以使用未命名的结构和联合字段重写struct
。
这样的事情:
#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;
}
当然,如果你有不同的类型,你应该使用不同的数组。
答案 2 :(得分:1)
通过int
访问struct
数组,反之亦然,如果这个答案可能有效,可能不会。然而,我现在对它与一般类型的使用并不那么有信心。将此保留为任何人添加/修改/删除的维基。
OP后来评论说struct
成员不是全部int
。哦,好吧。
如果所有成员都将永远int
...
按int
偏移量一次访问每个成员。
一些未经测试的代码来说明这个想法:
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);