FAQ Lite
Outras Questões Técnicas

[ 34.1 ] Porque meu compilador não consegue encontrar meu arquivo-header
#include "c:\test.hpp"?
[ 34.2 ] C++ tem novas regras de escopo para controle de loops for?
[ 34.3 ] Porque não posso sobrecarregar uma função pelo seu tipo de retorno?
[ 34.4 ] O que é persistência? O que é um objeto persistente?
[ 34.5 ] Porque ponto flutuante é tão impreciso? Porque não imprime 0.43?

[ 34.1 ] Porque meu compilador não consegue encontrar meu arquivo-header #include "c:\test.hpp"?

Porque "\t" é um caracter de tabulação.

Você deve usar barras normais ("/") ao invés de barras invertidas ("\") em seus nomes de arquivos #include, mesmo que o seu sistema operacional use barras invertidas, como é o caso em MS-DOS, Windows, OS/2, etc.

Por exemplo:

    #if 1
      #include "/version/next/alpha/beta/test.hpp"    // RIGHT!
    #else
      #include "\version\next\alpha\beta\test.hpp"    // WRONG!
    #endif 
Note que você deve usar barras normais ("/") em todos os seus nomes de arquivos, não apenas em arquivos #include.
Topo
[ 34.2 ] C++ tem novas regras de escopo para controle de loops for?

Sim.

O seguinte código já foi legal mas não é mais, porque o escopo de i agora esta apenas dentro do loop for:

    for (int i = 0; i < 10; ++i) {
      // ...
      if ( /* something weird */ )
        break;
      // ...
    }
    
    if (i != 10) {
      // We exited the loop early; handle this situation separately
      // ...
    } 
Exceto se você usar a variável de controle do loop for após o loop for, a nova regra de escopo não vai invalidar o seu código. Se a regra invalidar o seu código, na maioria dos casos o compilador vai lhe apresentar uma mensagem de erro de compilação como Variable i is not in scope.

Infelizmente é possível que essa nova regra silenciosamente leve o seu código a um funcionamento errado. Por exemplo, se você tiver uma variável global i, o código acima if (i != 10) silenciosamente altera o significado da variável i do loop for, simplesmente aplicando a nova regra de escopo. Isso não é bom. Se você estiver preocupado com isso, você deve verificar se seu compilador tem alguma opção para forçar o uso da regra antiga, quando compilar seus códigos antigos.

Nota: Você deve evitar ter o mesmo nome de variável em escopos aninhados, como uma variável global i e uma outra variável local também i. De fato, você deveria evitar o uso de variáveis globais sempre que possível. Se você aplicou esse padrão de codificação em seus códigos antigos de modo consistente, você não terá qualquer impacto em função da novas regras de escopo para variáveis de loop for.

Topo
[ 34.3 ] Porque não posso sobrecarregar uma função pelo seu tipo de retorno?

Se você declarar tanto char f() quanto float f(), o compilador vai lhe apresentar uma mensagem de erro, porque chamar simplesmente f() seria ambíguo.
Topo
[ 34.4 ] O que é persistência? O que é um objeto persistente?

Um objeto persistente pode continuar existindo mesmo após o encerramento da execução do programa que o criou. Objetos persistentes podem sobreviver a múltiplas versões do programa que o criou, sobreviver ao sistema de disco rígido, ao sistema operacional e até mesmo ao hardware no qual o sistema operacional estava em execução quando o objeto foi criado.

A finalidade de objetos persistentes é efetivamente armazenar seu código de funções membro em memória secundária, juntamente com os seus bits de dados (e os bits de dados de todos os seus objetos membro, e todos os seus objetos membro e classes base, etc). Isso não é simples de se fazer por meios próprios. Em c++ você tem que fazer isso por meios próprios, escrevendo todo o código necessário para lidar com os objetos persistentes. Gerenciadores de banco de dados C++/OO podem ajudar muito nessa tarefa.

Topo
[ 34.5 ] Porque ponto flutuante é tão impreciso? Porque não imprime 0.43?

    #include <iostream.h> 
    
    main()
    {
      float a = 1000.43;
      float b = 1000.0;
      cout << a - b << '\n';
    }  
Em uma implementação qualquer de C++, o código acima imprime 0.429993.

Justificativa: Frustração com arredondamentos, truncamentos e aproximações não é realmente um problema do C++; é um problema da ciência da computação. Contudo, as pessoas continuam perguntando sobre esse assunto para comp.lang.c++, o que se segue é a reprodução literal de uma resposta a essa questão.

Resposta: Ponto flutuante é uma aproximação. O padrão IEEE para 32 bits suporta um bit para sinal, 8 bits para o expoente e 23 bits para a mantissa. Devido ao fato de que uma mantissa, representada em sistema binário, tem a forma 1.xxxxx... o primeiro dígito um é suprimido e você tem efetivamente 24 bits para mantissa. O número 1000.43 (e muitos, muitos outros) não é representado exatamente em ponto flutuante ou formato duplo. 1000.43 é, na realidade, representado pelo seguinte padrão de bits (o s indica a posição do bit de sinal, e's indicam as posições do expoente, e os m's indicam as posições da mantissa):

        seeeeeeeemmmmmmmmmmmmmmmmmmmmmmm 
        01000100011110100001101110000101  
A mantissa é 1111101000.01101110000101 ou 1000 + 7045/16384. A fração é 0.429992675781. Com 24 bits de mantissa você tem uma precisão de 1 parte em 16M para ponto flutuante. O tipo double propicia uma maior precisão porque tem 53 bits de mantissa.
Topo Anterior Próximo Índice
C++ FAQ Lite
Copyright © 1991-98 by Marshall Cline Ph.D., cline@parashift.com
Tradução: Dagoberto Haele Arnaut

| Home | Bookmarks | Universidades | Para Saber mais | Universidades | WEB Directory | Mapa do site |