Трюки программирования
данные или, наоборот, восстановить состояние прошлой сессии работы с программой.
Собственно, все эти операции достаточно просто выполняются — в стандартной библиотеке любого языка программирования обязательно найдутся средства для обеспечения ввода и вывода, работы с внешними файлами. Но и тут находятся некоторые сложности, о которых, обычно, не задумываются.
Итак, как все это выглядит обычно? Имеется некоторая структура данных:
struct data_item
{
type_1 field_1; type_2 field_2; // ...
type_n field_n;
};
data_item i1;
Каким образом, например, сохранить информацию из i1 так, чтобы программа во время своего повторного запуска, смогла восстановить ее? Наиболее частое решение следующее:
FILE* f = fopen("file", "wb"); fwrite((char*)&i1, sizeof(i1), 1, f); fclose(f);
assert расставляется по вкусу, проверка инвариантов в данном примере не является сутью. Тем не менее, несмотря на частоту использования, этот вариант решения проблемы не верен.
Нет, он будет компилироваться и, даже будет работать. Мало того, будет работать и соответствующий код для чтения структуры:
FILE* f = fopen("file", "rb"); fread((char*)&i1, sizeof(i1), 1, f); fclose(f);
Что же тут неправильного? Ну что же, для этого придется немного пофилософствовать. Как бы много не говорили о том, что Си — это почти то же самое, что и ассемблер, не надо забывать, что он является все таки языком высокого уровня. Следовательно, в принципе, программа написанная на Си (или C++) может (теоретически) компилироваться на разных