Jump to content
Sign in to follow this  
fredericopissarra

Ainda sobre overflows de inteiros sinalizados

Recommended Posts

Posted (edited)

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...

Edited by fredericopissarra

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...