Ir para conteúdo

Ainda sobre overflows de inteiros sinalizados


fredericopissarra

Posts Recomendados

Para os puristas, testar por overflow de inteiros sinalizados, em C, é um "undefined behavior", como dito no artigo 6.5.6:8 da especificação ISO 9989:1999 (por exemplo). Mas, considerando que estive falando da plataforma Intel e em representações de complemento 2, os "macetes" que mostrei anteriormente funcionam muito bem.

Mas, se, mesmo assim, o purista exigir uma solução "correta", o GCC oferece funções built in para testes de overflow:

_Bool __builtin_add_overflow(a, b, [type] *res);
_Bool __builtin_sub_overflow(a, b, [type] *res);
_Bool __builtin_mul_overflow(a, b, [type] *res);

Esses são MACROS e existem funções equivalentes para cada "tipo", basta mudar o nome da operação para sadd, ssub ou smul (int), saddl, ssubl ou smull (long) ou saddll, ssubll ou smulll (long long). Troque o s por u para operações 'unsigned'...

Nos macros, "[type]" é apenas uma indicação que o ponteiro, que não pode ser NULL, deve apontar para os tipos de a e b... As funções retornam 1 se houver overflow e colocam o resultado no local apontado por res.

Existem ainda as funções built in de mesmos nomes, mas terminadas em _p. Elas não armazenam o resultado, mas usam o tipo do terceiro argumento (portanto não são funções, mas macros) para determinar se houve ou não overflow... A documentação diz que as operações são feitas com "precisão infinita" e só depois reduzida para a precisão do tipo do terceiro argumento. Mas, ao que parece, o compilador não usa aritmética de múltipla precisão, no sentido de bibliotecas como libgmp ou libmp.

Eis um exemplo de código:

#include <stdio.h>

int main( void )
{
  int o, r, a, b;

  // a + b, com certeza, vai dar overflow.
  a = (unsigned)-1 >> 1;
  b = 1;

  // Faz a adição e retorna o flag de overflow.
  o = __builtin_add_overflow(a, b, &r);

  printf( "%d + %d = %d (%sOVERFLOW)\n",
    a, b, r, o ? "" : "not " );
}

Sem otimizações a chamada ao built in fica assim, em assembly:

  xor ecx,ecx
  add eax,edx
  seto cl
  ; EAX sai com a soma e ECX com o booleano.

A vantagem de usar os built ins é que todo GCC suporta, para qualquer arquitetura...

Link para o comentário
Compartilhar em outros sites

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

  • Quem Está Navegando   0 membros estão online

    • Nenhum usuário registrado visualizando esta página.
×
×
  • Criar Novo...