#c #struct #initialization #nested
#c #struct #инициализация #вложенный
Вопрос:
Я использую стороннюю библиотеку, которая определяет эту структуру:
typedef struct
{
unsigned short nbDetectors;
//! structure of detector status
struct DetectorStatus
{
unsigned int lastError; //< last detector internal error
float temperature; //< detector temperature
detector_state state; //< detector state
unsigned short mode; //< detector mode
struct EnergyStatus
{
power_source powerSource; //< front-end power source
frontend_position frontendPosition; //< front-end position relative to the docking station
struct BatteryStatus
{
bool present; //< battery present or not in the detector
unsigned short charge; //< charge level of the battery (in %)
float voltageLevel; //< battery voltage level
float temperature; //< temperature of the battery
unsigned short chargeCycles; //< number of charge/discharge cycles
unsigned short accuracy; //< Expected accuracy for charge level (in %)
bool needCalibration;
} batteryStatus;
} * energyStatus;
struct GridStatus
{
detector_grid grid;
} * gridStatus;
} * detectorStatus;
} HardwareStatus;
Эта структура используется библиотекой в качестве данных, передаваемых одним из ее обратных вызовов. Так что это библиотека, которая заполняет ее, я только что прочитал ее. Пока все хорошо.
Но сейчас я пишу эмулятор для устройства, обрабатываемого этой библиотекой, так что теперь мне нужно заполнить одну из этих структур, и я не могу сделать это правильно.
Я попробовал это:
HardwareStatus status;
status.detectorStatus->temperature = 20 rand() % 10;
e.data = amp;status;
m_pContext->EventCallback( EVT_HARDWARE_STATUS, amp;e );
Когда я скомпилировал, я получил:
warning C4700: uninitialized local variable 'status' used
Тогда я понял… Указатели внутри struct указывают на мусор, хороший улов Visual Studio! Итак, я попытался начать с объявления экземпляра самой внутренней struct ( BatteryStatus
) , но это не скомпилировалось… потому что это не typedef’d (в нем говорится BatteryStatus
, что тип не определен)? Итак, я попал в тупик… Как мне заполнить структуру?
Комментарии:
1. Кроме того, чтобы установить BatteryStatus, вам нужно будет написать
EnergyStatus::BatteryStatus s; status.batteryStatus = s;
Примечание о квалификацииEnergyStatus::...
Ответ №1:
если вы хотите иметь все в стеке, это должно сделать это:
// Getting structs on the stack initialized to zero
HardwareStatus status = { 0 };
HardwareStatus::DetectorStatus detectorStatus = { 0 };
HardwareStatus::DetectorStatus::EnergyStatus energyStatus = { 0 };
HardwareStatus::DetectorStatus::GridStatus gridStatus = { 0 };
// "Linking" structs
detectorStatus.energyStatus = amp;energyStatus;
detectorStatus.gridStatus = amp;gridStatus;
status.detectorStatus = amp;detectorStatus;
// Now you can fill and use them
status.detectorStatus->temperature = 20 3 % 10;
//...
Комментарии:
1. Это работает, но без нулей в инициализации структуры (я все еще не могу редактировать сообщения других людей). Спасибо!
2. Пожалуйста, обратите внимание, что это решение может быть очень опасным, если вы планируете использовать переменную ‘status’, «созданную» таким образом, за пределами области, в которой выполняются эти определения. Это потому, что он указывает внутренне на данные, размещенные в стеке, и этот стек исчезнет. Я бы посоветовал вам распределять память динамически.
3. @Lev: Это очень верно, и это не проблема, структура передается обратному вызову, и как только это будет сделано, в этом больше нет необходимости
4. @dario_ramos: если это ваш вариант использования, тогда все хорошо 🙂 Просто убедитесь, что не выполняете с ним никаких асинхронных действий.
Ответ №2:
Вы могли бы инициализировать его по значению:
HardwareStatus status = {};
Если вы хотите создать экземпляр a BatteryStatus
, вы можете сделать это, полностью указав имя:
HardwareStatus::DetectorStatus::EnergyStatus::BatteryStatus bs;
Комментарии:
1. Это хорошее начало, более элегантное, чем memset’ting в 0, но… Я все еще не могу коснуться
detectorStatus->temperature
, потомуdetectorStatus
что это недопустимый указатель2.
HardwareStatus status = {}; status.detectorStatus->temperature = 20 rand() % 10;
Это скомпилировано для меня, кроме предупреждения о преобразовании int в float .3. @Gnawme: ваш код присваивает значение через нулевой указатель. Почему вы ожидаете, что это сработает? То, что он строит, не означает, что это правильно.
4. @dario: Вы еще не создали экземпляр
DetectorStatus
fordetectorStatus
, на который можно указать!5. @JohnDibling: я согласился с вашей инициализацией значения; Я должен был более внимательно прочитать вопрос OP…
Ответ №3:
вы пробовали memset’ing структуру в 0 ?
Комментарии:
1.
memset(amp;status, 0, sizeof(status));
2. Что ж, это устраняет предупреждение, но теперь все указатели struct указывают на NULL (здесь 0)… Так что я все еще не могу установить
detectorStatus->temperature
(что на самом деле единственное, что я хочу сделать)