Возможный сценарий реальной ситуации, когда это происходит, когда библиотека базы данных, написанная в дни, когда пространство на жестком диске было очень ограничено, использовала один байт для хранения поля даты в году (например, 11-NOV-1973 бы 73на год). Но когда наступил 2000 год, этого уже было бы недостаточно, и тогда год должен был быть сохранен как короткое (16-разрядное) целое число. Соответствующий (очень упрощенный) заголовок для этой библиотеки может быть таким:
// dbEntry.h
typedef struct _dbEntry dbEntry;
dbEntry* CreateDBE(int day, int month, int year, int otherData);
void DeleteDBE(dbEntry* entry);
int GetYear(dbEntry* entry);
И «клиентская» программа будет:
#include <stdio.h>
#include "dbEntry.h"
int main()
{
int dataBlob = 42;
dbEntry* test = CreateDBE(17, 11, 2019, dataBlob);
//...
int year = GetYear(test);
printf("Year = %d\n", year);
//...
DeleteDBE(test);
return 0;
}
«Оригинальная» реализация:
#include <stdlib.h>
#include "dbEntry.h"
struct _dbEntry {
unsigned char d;
unsigned char m;
unsigned char y; // Fails at Y2K!
int dummyData;
};
dbEntry* CreateDBE(int day, int month, int year, int otherData)
{
dbEntry* local = malloc(sizeof(dbEntry));
local->d = (unsigned char)(day);
local->m = (unsigned char)(month);
local->y = (unsigned char)(year % 100);
local->dummyData = otherData;
return local;
}
void DeleteDBE(dbEntry* entry)
{
free(entry);
}
int GetYear(dbEntry* entry)
{
return (int)(entry->y);
}
Затем, при приближении 2000 года, этот файл реализации будет изменен следующим образом (все остальное остается без изменений):
struct _dbEntry {
unsigned char d;
unsigned char m;
unsigned short y; // Can now differentiate 1969 from 2069
int dummyData;
};
dbEntry* CreateDBE(int day, int month, int year, int otherData)
{
dbEntry* local = malloc(sizeof(dbEntry));
local->d = (unsigned char)(day);
local->m = (unsigned char)(month);
local->y = (unsigned short)(year);
local->dummyData = otherData;
return local;
}
Когда клиент должен быть обновлен для использования новой (безопасной для Y2K) версии, никаких изменений кода не потребуется. На самом деле, вам даже может не потребоваться повторная компиляция: может быть достаточно простой повторной ссылки на обновленную библиотеку объектов (если это так) .
structэто черный ящик с неизвестными внутренностями. Если клиент не знает внутренности, он никогда не сможет получить к ним доступ напрямую, и вы можете изменить их по своему желанию. Это похоже на инкапсуляцию в ООП. Внутренние компоненты являются частными, и вы можете изменить объект только с помощью открытых методов.