[34] Miscellaneous technical issues
(Part of C++ FAQ Lite, Copyright © 1991-96, Marshall Cline, cline@parashift.com)


FAQs in section [34]:


[34.1] Why can't the compiler find my header file in #include "c:\test.hpp" ?

Because "\t" is a tab character.

You should use forward slashes ("/") rather than backslashes ("\") in your #include filenames, even on an operating system that uses backslashes such as DOS, Windows, OS/2, etc. For example:

    #if 1
      #include "/version/next/alpha/beta/test.hpp"    // RIGHT!
    #else
      #include "\version\next\alpha\beta\test.hpp"    
// WRONG!
    #endif

Note that you should use forward slashes ("/") on all your filenames, not just on your #include files.

TopBottomPrevious sectionNext section ]


[34.2] Does C++ have new scoping rules for for loops?

Yep.

The following code used to be legal, but not any more, sinc i's scope is now inside the for loop only:

    for (int i = 0; i < 10; ++i) {
      
// ...
      if ( 
/* something wierd */ )
        break;
      
// ...
    }
    
    if (i != 10) {
      
// We exited the loop early; handle this situation separately
      
// ...
    }

Unless you use a for loop variable after the for loop, the new scoping rule won't break your code. If it does break your code, in most cases the compiler will give you a compile-time error message such as "Variable i is not in scope".

Unfortunately it is possible that this new rule will silently cause your code to do the wrong thing. For example, if you have a global variable i, the above code if (i != 10) silently change in meaning from the for loop variable i under the old rule to the global variable i under the new rule. This is not good. If you're concerned, you should check with your compiler to see if it has some option that forces it to use the old rules with your old code.

Note: You should avoid having the same variable name nested scopes, such as a global i and a local i. In fact, you should avoid globals althogether whenever you can. If you abided by these coding standards in your old code, you won't be hurt by the new scoping rules for for loop variables.

TopBottomPrevious sectionNext section ]


[34.3] Why can't I overload a function by its return type?

If you declare both char f() and float f(), the compiler gives you an error message, since calling simply f() would be ambiguous.

TopBottomPrevious sectionNext section ]


[34.4] What is "persistence"? What is a "persistent object"?

A persistent object can live after the program which created it has stopped. Persistent objects can even outlive different versions of the creating program, can outlive the disk system, the operating system, or even the hardware on which the OS was running when they were created.

The challenge with persistent objects is to effectively store their member function code out on secondary storage along with their data bits (and the data bits and member function code of all member objects, and of all their member objects and base classes, etc). This is non-trivial when you have to do it yourself. In C++, you have to do it yourself. C++/OO databases can help hide the mechanism for all this.

TopBottomPrevious sectionNext section ]


[34.5] Why is floating point so inaccurate? Why doesn't this print 0.43?

    #include <iostream.h> 
    
    main()
    {
      float a = 1000.43;
      float b = 1000.0;
      cout << a - b << '\n';
    } 

(On one C++ implementation, this prints 0.429993)

Disclaimer: Frustration with rounding/truncation/approximation isn't really a C++ issue; it's a computer science issue. However, people keep asking about it on comp.lang.c++, so what follows is a nominal answer.

Answer: Floating point is an approximation. The IEEE standard for 32 bit float supports 1 bit of sign, 8 bits of exponent, and 23 bits of mantissa. Since a normalized binary-point mantissa always has the form 1.xxxxx... the leading 1 is dropped and you get effectively 24 bits of mantissa. The number 1000.43 (and many, many others) is not exactly representable in float or double format. 1000.43 is actually represented as the following bitpattern (the "s" shows the position of the sign bit, the "e"s show the positions of the exponent bits, and the "m"s show the positions of the mantissa bits):

        seeeeeeeemmmmmmmmmmmmmmmmmmmmmmm 
        01000100011110100001101110000101 

The shifted mantissa is 1111101000.01101110000101 or 1000 + 7045/16384. The fractional part is 0.429992675781. With 24 bits of mantissa you only get about 1 part in 16M of precision for float. The double type provides more precision (53 bits of mantissa).

TopBottomPrevious sectionNext section ]


 E-mail the author
C++ FAQ LiteTable of contentsSubject indexAbout the author©Download your own copy ]
Revised Sep 8, 1997