Um possível cenário do mundo real onde isso ocorreria é quando uma biblioteca de banco de dados, escrita nos dias em que o espaço no disco rígido era muito limitado, usava um único byte para armazenar o campo 'ano' de uma data (por exemplo, 11 de novembro de 1973 teria 73
para o ano). Mas, quando o ano 2000 chegou, isso não seria mais suficiente e o ano teve que ser armazenado como um número inteiro curto (16 bits). O cabeçalho relevante (muito simplificado) para esta biblioteca pode ser o seguinte:
// dbEntry.h
typedef struct _dbEntry dbEntry;
dbEntry* CreateDBE(int day, int month, int year, int otherData);
void DeleteDBE(dbEntry* entry);
int GetYear(dbEntry* entry);
E um programa 'cliente' seria:
#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;
}
A implementação 'original':
#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);
}
Em seguida, na abordagem do Y2K, esse arquivo de implementação seria alterado da seguinte maneira (tudo o mais permanece intocado):
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;
}
Quando o cliente precisar ser atualizado para usar a nova versão (segura para o Y2K), nenhuma alteração de código será necessária. De fato, talvez você nem precise recompilar: basta vincular novamente a biblioteca de objetos atualizada (se é isso que é) a ser suficiente.
struct
é uma caixa preta com componentes internos desconhecidos. Se o cliente não souber os internos, ele nunca poderá acessá-los diretamente e você poderá alterá-los à vontade. Isso é semelhante ao encapsulamento no OOP. Os internos são privados e você só altera o objeto usando métodos públicos.