У меня есть структура структуры с членами, как это

typedef struct{
    double xMin;
    double yMin;
    double zMin;
    double xMax;
    double yMax;
    double zMax;
    double xMedian;
    double yMedian;
    double zMedian;
    double xMean;
    double yMean;
    double zMean;
    double xVar;
    double yVar;
    double zVar;
    double xStD;
    double yStD;
    double zStD;
}featureSet_t;

typedef struct{
    featureSet_t acc_features;
    featureSet_t gyr_features;
    featureSet_t mag_features;
}combinedFeatureSet_t; 

combinedFeatureSet_t featureSetOfPolledData;
double copy[54] = {0};

Теперь я хочу скопировать членов вышеупомянутого экземпляра в массив двойной скажем, например,

copy[0] =  featureSetOfPolledData.acc_features.xMin;
..
..
copy[53] =  featureSetOfPolledData.mag_features.zstD;

Это слишком утомительно. Пожалуйста, помогите, что лучший способ сделать это.

1
Coppers Copernicus 3 Май 2019 в 16:44

4 ответа

Лучший ответ

Лучшее решение - просто использовать memcpy. Вы должны будете защититься от заполнения в структуре - в этом случае их не должно быть, но рекомендуется всегда проверять время компиляции:

_Static_assert(sizeof(featureSetOfPolledData) == sizeof(double[54]), 
               "Unexpected padding detected.");

Как только это проверено, тогда просто весело memcpy прочь:

memcpy(copy, &featureSetOfPolledData, sizeof(double[54]));

Если вам по какой-то причине необходимо индексировать отдельные имена элементов, и изменение типов является вариантом, рассмотрите возможность использования союзов:

typedef union
{
  struct
  {
    double xMin;
    double yMin;
    double zMin;
    double xMax;
    double yMax;
    double zMax;
    double xMedian;
    double yMedian;
    double zMedian;
    double xMean;
    double yMean;
    double zMean;
    double xVar;
    double yVar;
    double zVar;
    double xStD;
    double yStD;
    double zStD;
  };
  double array [18];
}featureSet_t;

typedef union
{
  struct
  {
    featureSet_t acc_features;
    featureSet_t gyr_features;
    featureSet_t mag_features;
  };
  double array [18*3];  
}combinedFeatureSet_t; 

Теперь можно было бы делать такие вещи, как:

for(size_t i=0; i<54; i++)
{
  copy[i] = featureSetOfPolledData.array[i];
}

Но также для доступа к отдельным элементам по имени:

featureSetOfPolledData.acc_features.xMin = 1.0;
3
Lundin 3 Май 2019 в 14:04

Индивидуальное присвоение элементов структуры вашему массиву, как вы описываете, является единственным строго соответствующим способом выполнить работу. Любая другая альтернатива требует предположений о расположении членов структуры, и C не дает достаточно сильных гарантий для поддержки того, что вы хотите.

Однако, если вы хотите предположить, что featureSet_t размещен без каких-либо дополнений между членами, или если вы можете использовать расширение реализации, чтобы обеспечить это, и если вы хотите, чтобы ваш массив заполнялся в порядке элементов структуры, один члены структуры после других, тогда вы можете использовать memcpy() для этого:

double copy[54];

memcpy(copy,      &featureSetOfPolledData.acc_features, 18 * sizeof(double));
memcpy(copy + 18, &featureSetOfPolledData.gyr_features, 18 * sizeof(double));
memcpy(copy + 36, &featureSetOfPolledData.mag_features, 18 * sizeof(double));

Это обеспечивает довольно хорошую простоту кода в обмен на нетривиальные предположения о структуре структуры, которые, тем не менее, , вероятно, верны на практике. Можно предположить, что вам может сойти с рук только один memcpy() из общего featureSetOfPolledData объекта, но IMO, минимальное дополнительное упрощение кода, достигнутое таким образом, не оправдывает более сильные предположения о компоновке.

1
John Bollinger 3 Май 2019 в 13:57

Самое близкое, что может сработать, если придерживаться стандарта, это создать union структуры и массива и проверить, что они имеют одинаковый размер:

static_assert(sizeof(combinedFeatureSet_t) == sizeof(double [54]), "size mismatch");

typedef union {
    combinedFeatureSet_t featureset_struct;
    double featureset_list[54];
} featureset_u;

featureset_u u;
u.featureset_struct = featureSetOfPolledData;
// read u.featureset_list

static_assert проверяет, что структура не имеет внутреннего заполнения. При этом члены массива перекрывают в точности элементы структуры и имеют одинаковый тип.

С помощью этого объединения вы можете свободно читать из массива и записывать в структуру или наоборот.

1
dbush 3 Май 2019 в 14:05

Вероятно, вы можете создать функцию, взяв combinedFeatureSet_t и вернув double array. Он вызывает другую функцию, возвращающую double array из вашего featureSet_t для каждого featureSet_t. Оттуда вам нужно будет только вызвать первую функцию, чтобы получить array.

0
Samuel L. 3 Май 2019 в 14:02