Olá professor.

Minha intenção não é tentar ser chato, pointless nitpicking, ou qualquer coisa assim; mas creio que dois exemplos presentes nos slides da aula de hoje de manhã (Semântica Formal N) deixaram algumas pessoas confusas.

No exemplo 2:

   i = 0 ;
   i = i + i++;
   i = 0 ;
   i = i++ + i ;
   i = 0 ,
   i = i++ + i++;

Isto viola o item 6.5/2 do ISO 9899:1999, que diz:

2. Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be read only to determine the value to be stored. (70)

E no rodapé da página, a anotação 70 diz:

70) This paragraph renders undefined statement expressions such as

       i = ++i + 1;
       a[i++] = i;

while allowing

       i = i + 1;
       a[i] = i;

E, naturalmente o C++ mantém a mesma semântica; o item 5/4 do ISO 14882:2003 diz essencialmente a mesma coisa, e dá como exemplo:

   i = v[i++];        // the behavior is unspecified
   i = 7, i++, i++; // i becomes 9
   i = ++i + 1;    // the behavior is unspecified
   i = i + 1;        // the value of i is incremented

Este tipo de construção é inclusive um FAQ: http://c-faq.com/ansi/experiment.html Logo o código não é bem formado, pois a semântica da linguagem proíbe o que está sendo feito.

Outro problema é o que foi dito do exemplo 3:

       float q = 3.0 / 7.0 ;
       if( q == 3.0/7.0 )
               printf( "Tudo bem.\n" );
       else
               printf( "Tudo ruim.\n" ) ;

Foi dito que o código sempre imprime “Tudo ruim”; mas na verdade este código pode imprimir qualquer das duas mensagens, basta que a representação de ponto flutuante em questão seja capaz de representar a fração 3/7 da mesma forma tanto em double quanto em float; se a implementação de ponto flutuante for de base 7, ou se float e double forem iguais. De fato, float, double e long double podem ser todos idênticos (com o GCC em i386 é fácil controlar o resultado do if usando a flag “-fshort-double”; é possível que alguma arquitetura não possua tipos de ponto flutuante menores que o usado por double, assim float sempre será o mesmo que double). O código do exemplo apenas expressa uma característica de como a implementação se comporta, da mesma forma que:

       unsigned i = 65535;
       i++;
       if (i)
               printf( "Tudo bem.\n" );
       else
               printf( "Tudo ruim.\n" ) ;

Se int tiver 16 ou 32 bits, o resultado do teste pode ser diferente.

— Daniel K. O.

Daniel,

concordo com a tua discussão dos exemplos; obrigado pelo trabalho. Basei mei pesquisa no padrão 14882:1998 e não achei nada lá. Da para ver que já sou mais velho, usando padrões antigas. LOL Acho que os exemplos ao menos servem a illustrar meu assunto na introdução: a dificuldade e a necessidade para semânticas claras e formais para as linguagens.

– Marcus