Na programação C (e programação em geral), pré -condições e pós -condições são afirmações sobre o estado das variáveis ou estruturas de dados de um programa que devem manter
antes de e
depois de a execução de uma função, respectivamente. Eles são importantes para projetar código robusto e confiável, especialmente em sistemas complexos. Embora C não tenha suporte de palavras-chave embutido para pré-condições formais e pós-condições, como alguns outros idiomas (por exemplo, contratos em Eiffel), os conceitos ainda são cruciais e podem ser implementados usando afirmações e comentários.
Aqui está um colapso da diferença:
1. Pré -condição: *
Definição: Uma condição que
deve ser verdadeira * Antes de* uma função é chamada para que a função funcione corretamente e garanta seu comportamento. É a responsabilidade * do * chamador * garantir que as pré -condições sejam atendidas. Se uma pré -condição for violada, o comportamento da função será indefinido; Pode travar, produzir resultados incorretos ou se comportar imprevisivelmente.
*
Objetivo: *
Esclareça as entradas e o ambiente esperados: As pré -condições documentam o que uma função espera. Isso facilita a compreensão e o uso da função.
*
Prevenção de erros e bugs: Ao verificar as pré -condições (usando asserções), você pode detectar e evitar erros no início do processo de desenvolvimento.
*
Ativar otimização: Se uma função souber que certas condições sempre serão verdadeiras, ela pode executar otimizações que não seriam seguras de outra forma.
*
Documentação: A documentação clara permite que outros desenvolvedores usem a função corretamente.
*
Responsabilidade: O * chamador * da função é responsável por garantir que todas as pré -condições sejam verdadeiras antes de chamar a função.
*
Exemplo: `` `c
#include
#include
// função para calcular o fatorial de um número
int fatorial (int n) {
// pré-condição:n deve ser não negativo
assert (n> =0);
if (n ==0) {
retornar 1;
} outro {
retornar n * fatorial (n - 1);
}
}
int main () {
int resultado =fatorial (5); // pré -condição satisfeita
printf ("Fatorial de 5:%d \ n", resultado);
// Fatorial (-1); // A pré -condição violada! Isso causará uma falha de afirmação.
retornar 0;
}
`` `
Neste exemplo, a função "fatorial" tem uma condição prévia de que `n` deve ser não negativo. O `assert (n> =0)` declaração verifica esta pré -condição. Se `n` for negativo, a afirmação falhará e o programa será encerrado (em uma construção de depuração).
2. Postcondição:
* Definição: Uma condição que deve ser verdadeira * Após* uma função executada com sucesso. Ele descreve o estado do programa (variáveis, estruturas de dados, valor de retorno) após a função concluir sua tarefa. É responsabilidade da * função * garantir que as condições postais sejam atendidas, * assumindo que * as pré -condições fossem atendidas.
* Objetivo:
* Garanta o efeito da função: As condições postais documentam o que a função * promete * fazer.
* Verifique a correção: Ao verificar as pós -condicionas (usando asserções), você pode verificar se a função está produzindo os resultados esperados.
* facilitar a depuração: Se uma condição pós -condição for violada, indica um bug dentro da própria função.
* Documentação: A documentação clara permite que outros desenvolvedores entendam o comportamento da função.
* Responsabilidade: A função * em si * é responsável por garantir que todas as condições postais sejam verdadeiras antes de retornar.
* Exemplo:
`` `c
#include
#include
// função para calcular o quadrado de um número
Int Square (int x) {
int resultado =x * x;
// pós-condição:o resultado deve ser não negativo (se x for um número inteiro)
assert (resultado> =0); // Isso pode falhar devido ao excesso inteiro se X for muito grande.
resultado de retorno;
}
int main () {
int resultado =quadrado (5);
printf ("quadrado de 5:%d \ n", resultado);
int grande_number =100000; // pode causar transbordamento
resultado =quadrado (grande_number); // O pós -condição pode falhar devido ao excesso.
printf ("quadrado de %d:%d \ n", grande_number, resultado);
retornar 0;
}
`` `
Neste exemplo, a função `square` possui uma condição pós-condição de que` resultado` deve ser não negativo (assumindo que 'x` seja um número inteiro). O `assert (resultado> =0)` Declaração verifica esta condição post. Se o resultado for negativo (devido ao excesso inteiro, por exemplo), a afirmação falhará.
As diferenças de chave resumidas:
| Recurso | Pré -condição | PostCondition |
| ---------------- | ------------------------------------------------ | ------------------------------------------------ |
| Tempo | Verificado * Antes * da função Executa | Verificado * Após * a função executa |
| Responsabilidade | Chamador da função | Função em si |
| propósito | Definir entrada e ambiente esperados | Defina o comportamento garantido e o efeito da função |
| Violação | Indica um problema no código de chamada * | Indica um problema * dentro da função * |
| garantias | A função pode funcionar corretamente | A função terá alcançado seu efeito pretendido |
Como implementar em c:
Como C não possui suporte interno para pré-condições e pós-condições, a abordagem padrão é usar:
1. `assert ()` macro (de ``) :Esta é a maneira mais comum de verificar as condições. As afirmações geralmente são ativadas nas compilações de depuração (por exemplo, com a bandeira do compilador `-DDEBUG`) e desativadas nas compilações de liberação. Isso significa que as verificações acontecem durante o desenvolvimento, mas são otimizadas no produto final para evitar a sobrecarga de desempenho.
2. `#ifdef Debug` Blocks :Você também pode usar o `#IFDEF Debug` para incluir condicionalmente as verificações de pré -condição e pós -condição mais complexas que podem envolver mais do que uma comparação simples.
3. Comentários :Mesmo que você não use afirmações, é crucial documentar pré -condições e pós -condições nos comentários para tornar seu código mais compreensível.
4. Estruturas de teste: Considere o uso de estruturas de teste que suportam verificações pré/pós-condição para facilitar o teste de unidade.
Exemplo com pré -condições, pós -condicionas e comentários combinados:
`` `c
#include
#include
/**
* @brief calcula o poder de um número (base aumentada ao expoente).
*
* @param base o número base (número inteiro).
* Exponente @param O expoente (número inteiro não negativo).
*
* Exponente @Pre> =0 (o expoente deve ser não negativo).
* @pre base! =0 || expoente! =0 (base e expoente não 0 0 - evita comportamento indefinido)
*
* @Post Retorna a base aumentada ao poder do expoente.
* @Post Se o expoente for 0, o resultado é 1 (exceto base =0, que não é permitido).
*
* @return o resultado da base aumentada ao poder do expoente.
* Retorna 1 se o expoente for 0.
*/
int Power (int base, int expoente) {
// pré -condições:
assert (exponente> =0);
assert (base! =0 || expoente! =0); // impedir o comportamento indefinido com 0^0
int resultado =1;
para (int i =0; i resultado *=base;
}
// PostConditions:
if (exponent ==0) {
assert (resultado ==1); // Verifique se há caso base
}
resultado de retorno;
}
int main () {
int resultado =potência (2, 3); // 2^3 =8
printf ("2^3 =%d \ n", resultado);
resultado =poder (5, 0); // 5^0 =1
printf ("5^0 =%d \ n", resultado);
// poder (0,0); // Isso acionará a afirmação.
retornar 0;
}
`` `
Benefícios do uso de pré -condições e pós -condicionas:
* Qualidade de código aprimorada: Eles o forçam a pensar cuidadosamente sobre as suposições e garantias de suas funções.
* Depuração mais fácil: As afirmações ajudam a capturar erros mais cedo e identificar a fonte de problemas.
* Melhor documentação: Eles documentam claramente o comportamento esperado de suas funções.
* Manutenção aumentada: Eles facilitam o entendimento e a modificação do seu código, o que reduz o risco de introduzir bugs.
* Verificação formal: Em alguns casos, pré -condições e pós -condições podem ser usadas com ferramentas formais de verificação para provar a correção do seu código.
Ao incorporar pré -condições e pós -condições ao seu código C (mesmo que apenas usando comentários e afirmações), você pode escrever um software mais robusto, confiável e sustentável.