вопрос: имеется такой фрагмент Код (Text): struct Option { const char * const Name; int Value; }; struct Settings { Option ScreenWidth; Option ScreenHeight; }; можно ли как-то обращаться к полям структуры Settings как к элементам массива, допустим при сохранении ее в ini файл?
Ты в файл его не сохранишь. Придумывай другую структуру. Name - это указатель, адрес в памяти. Сохрани в файл, перезапусти приложение и считай из файла - по этому адресу будет мусор. Нужно сохранять сами значения, а не адрес в памяти. Насчёт массивов - не понятно чего ты хотел. Массив структур Settings? Можно, а почему нет?
cppasm думаю, в моем случае не будет, образ грузится по фиксированному адресу, смещения строк в нем постоянны. я имел в виду, возможно ли написать что-то похожее на Код (Text): struct Option { const char * const Name; int Value; }; struct Settings { Option ScreenWidth; Option ScreenHeight; }; Settings SModified; for (int i=0; i<sizeof(Settings)/sizeof(Option); i++) fprintf(file, "%s=%i\n", SModified[i].Name, &SModified[i].Value);
пишите, кто вам мешает... только вы написали неправильно и это канеш плохой стиль, нормальные программисты так не пишут... SModified, если бы он был у вас указателем ... то SModified[1] - будет за уже структурой (тк размер структуры Settings больше размера структуры Option)... надо преобразовать указатель Settings к указателю на Option... и амперсанд перед SModified.Value не понятно зачем поставлен...
вот так примерно: Код (Text): struct Option { const char * const Name; int Value; }; struct Settings { Option ScreenWidth; Option ScreenHeight; }; Settings SModified; Option* opt = (Option*)&SModified; for (int i=0; i<sizeof(Settings)/sizeof(Option); i++) { fprintf(file, "%s=%i\n", opt[i].Name, opt[i].Value); } и на злобу дня: это все справедливо, если обе структуры являются pod-типами, хотя они скорее всего ими будут...
Фиговый это метод, выравнивание может всё поломать и POD-типы не спасут. Если нужен массив, чего не сделать массив? Код (Text): struct Settings { Option Options[CONST_NUM]; }; А если загрузится по другому адресу, а если строки динамические? Короче плохо так писать.
не-не-не) PE-файл без релоков не загрузится по другому адресу... при сохранении строк никаких проблем не может возникнуть... при загрузке - другой вопрос, они уже в секции данных, грузить строку надо в отдельный буффер и искать адрес на нее в памяти... хотя если параметры всегда пишутся одинакого, то можно их вообще не грузить... а вообще ТС неплохо бы подучить язык, чтоб не возникало таких вопросов и чтобы не генерить гуано-код... ну или перейти на си-шарп/руби/питон...
На испытанных компиляторах - нет, они всячески этому противостоят По стандарту элементы массива обязательно идут последовательно (без промежутков), а между полями структуры может добавляться выравнивание. Вот смоделированная ситуация для gcc: Код (Text): struct OPTION { int id; char data; } __attribute__((packed)); typedef struct OPTION OPTION; struct SETTINGS_ARR { OPTION options[4] __attribute__((aligned(8))); }; typedef struct SETTINGS_ARR SETTINGS_ARR; struct SETTINGS_STR { OPTION option1 __attribute__((aligned(8))); OPTION option2 __attribute__((aligned(8))); OPTION option3 __attribute__((aligned(8))); OPTION option4 __attribute__((aligned(8))); }; typedef struct SETTINGS_STR SETTINGS_STR; int main(void) { printf("sizeof(OPTION)=%d\n" "sizeof(SETTINGS_ARR)=%d\n" "sizeof(SETTINGS_STR)=%d\n", sizeof(OPTION), sizeof(SETTINGS_ARR), sizeof(SETTINGS_STR)); return 0; } Вывод: Напишу сразу - понятно что я это сделал намеренно чтобы показать что я имею ввиду, т.е. ситуация довольно искусственная. Если вручную не задавать выравнивания, компилятор всячески пытается недопустить этой ситуации и в основном просто выравнивает размер структуры sizeof(OPTION)=8, хотя этого и не требуется (при sizeof(OPTION)=5 все поля структуры имеют то же выравнивание). Это понятно. Просто это куча ограничений, зачем такой код писать? Сохранять надо данные, а не адрес в памяти, который в общем случае при разных запусках будет разным.
cppasm Выравнивание делается для оптимизации по скорости, а раз так, то нет разницы структура это или массив. Насчёт промежутков я не понял, выравнивание это не промежутки.
Во-первых - выравнивание это "промежутки", добавление "пустых" байтов для получения адреса следующего поля кратного определённому числу. Вот пример: Код (Text): struct TEST { char x; int y; }; При включённом выравнивании данные будут расположены так: x - 1 байт alignment - 3 байта для выравнивания, не используется (это я назвал промежутком) y - 4 байта Есть разница структура это или массив. Пусть есть упакованная структура: Код (Text): struct TEST { int i_val; char c_val; }; Размер будет 5 байт. Теперь если создать структуру, содержащую массив этих структур: Код (Text): struct COMPOUND { struct TEST test_arr[2]; }; Выравниваться будет адрес test_arr, в самом массиве данные будут идти непрерывно: 0 элемент: i_val 4 байта, c_val 1 байт 1 элемент: i_val 4 байта, c_val 1 байт Если создать структуру с двумя вложенными структурами: Код (Text): struct COMPOUND { struct TEST test1; struct TEST test2; }; Выравниваться будет адрес каждого поля структуры, т.е. адрес test1 и адрес test2. Получим test1: i_val 4 байта, c_val 1 байт alignment: 3 байта для выравнивания адреса test2 на границу двойного слова test2: i_val 4 байта, c_val 1 байт Разницу видишь? Расположение в памяти будет разное. Для массива гарантируется что элементы идут последовательно, между ними данные для выравнивания добавляться не могут. А между полями структуры - могут.
Не, ну если он забивается на то, что у него исполняемый модуль всегда будет по одному и тому же адресу грузиться, то и твой метод использовать можно. Из всех компиляторов которые я протестировал все нормально эту ситуацию разруливают если вручную с выравниваением не извращаться. Просто стандартом это не гарантировано, и однажды можно наколоться.
cppasm А если поиграться на одном и том же компиляторе с опциями компиляции/оптимизации? Вот тут-то всё и вскроется.
По выравниванию от Мелкомягких есть #pragma pack struct Option { const char * const Name; int Value; }; struct Settings { union { struct { Option ScreenWidth; Option ScreenHeight; }; Option ArrayOption[2]; //На самом деле число здесь не имеет смысла. } };