Thread: Leading Underscores

  1. #1
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413

    Leading Underscores

    It has been mentioned here that (all) identifiers (or only in (all) pre-processor directives?) with leading underscores are reserved for the implementation.

    So something like:

    #ifndef _HEADER_H
    #define _HEADER_H

    to implement header guards would be bad practice.

    However, I cant seem to find where this is stated in ISO/IEC 14882:2003
    Does anyone know where I can find the relevant information in the standard?
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  2. #2
    & the hat of GPL slaying Thantos's Avatar
    Join Date
    Sep 2001
    Posts
    5,681
    Its all identifiers and its not part of the standard. Its just convention.

  3. #3
    S Sang-drax's Avatar
    Join Date
    May 2002
    Location
    Göteborg, Sweden
    Posts
    2,072
    Yes, some identifiers are reserved for the implementation to use and is illegal to use in your program.

    I quote the standard:
    17.4.3.1.2 Global names
    1 Certain sets of names and function signatures are always reserved to the implementation:
    — Each name that contains a double underscore (_ _) or begins with an underscore followed by an uppercase
    letter (2.11) is reserved to the implementation for any use.
    — Each name that begins with an underscore is reserved to the implementation for use as a name in the global namespace. (Such names are also reserved in namespace ::std)
    So you can never use identifiers that contains double underscores and you may not use identifiers that begin with a single underscore in the global namespace or ::std.
    Last edited by Sang-drax : Tomorrow at 02:21 AM. Reason: Time travelling

  4. #4
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >Its all identifiers and its not part of the standard.
    It is standard, but not for all identifiers. The convention is all identifiers because the rules are easy to break without knowing it.
    My best code is written with the delete key.

  5. #5
    & the hat of GPL slaying Thantos's Avatar
    Join Date
    Sep 2001
    Posts
    5,681
    I stand corrected

    You know I think I'm gonna buy a copy of the standard with this next paycheck

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    okay, Sang-drax seems to have given me the right spot

    It is standard, but not for all identifiers. The convention is all identifiers
    The standard seems to include all identifiers too, since "Each name that begins with an underscore is reserved to the implementation for use as a name in the global namespace."
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  7. #7
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >The standard seems to include all identifiers too
    Okay, but in proving this statement be sure not to contradict yourself.

    >since "Each name that begins with an underscore is reserved to the implementation for use as a name in the global namespace."
    Ooh, so close. Notice the "in the global namespace" part. There are quite a few places that do not count as the global namespace, most notably class members and local variables. The following is perfectly legal:
    Code:
    #include <iostream>
    
    namespace A {
      class _A {
      public:
        int _a;
    
        _A(): _a ( 10 ) {}
    
        void _print() { std::cout<< _a <<std::endl; }
      };
    }
    
    int main()
    {
      int _b = 20;
      A::_A _c;
    
      std::cout<< _b <<std::endl;
      _c._print();
    }
    It's ugly as sin, but conforms to the standard.

    >You know I think I'm gonna buy a copy of the standard with this next paycheck
    The electronic standard is only $18US, and the Wiley book is $64US. Not exactly bank-breaking prices, and they're worth their weight in gold.
    My best code is written with the delete key.

  8. #8
    Registered User jlou's Avatar
    Join Date
    Jul 2003
    Posts
    1,090
    or begins with an underscore followed by an uppercase
    letter (2.11)
    seems to say that your _A class is not legal.

  9. #9
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >seems to say that your _A class is not legal.
    It does, doesn't it? The rules are convoluted, and this is a particularly tricky area. Here's my interpretation:

    As per section 17.4.3.1, we know that the following kinds of names are reserved: Macros, global names, and names with external linkage.

    The underscore rules are in the subclause about global names, and I quote:
    Certain sets of names and function signatures are always reserved to the implementation:

    -- Each name that contains a double underscore (__) or begins with an underscore followed by an upper-
    case letter (2.11) is reserved to the implementation for any use.

    -- Each name that begins with an underscore is reserved to the implementation for use as a name in the
    global namespace.
    The second item goes on to mention a footnote that says the std namespace is included in the restrictions.

    This is where it gets tricky and it's hard to tell which interpretation is correct. I say (until someone corrects me with a solid reason) that because _A is not a global name (it's enclosed in the A namespace), this subclause does not apply. My reasoning for this is from section 3.3.5:
    The outermost declarative region of a translation unit is also a namespace, called the global namespace. A name declared in the global namespace has global namespace scope (also called global scope).

    ...

    Names with global namespace scope are said to be global.
    Because _A is not declared in the outermost declarative region of the translation unit, it cannot be a global name.

    However, because items in a namespace may have external linkage, the restrictions in that subclause could apply, but none of them fit for a class declaration. They are summarized as follows:

    1) An object with external linkage in a header. Classes are not objects.

    2) A global function signature with external linkage in a header. Classes are not function signatures.

    3) A name with two consecutive underscores in the name. _A doesn't violate this.

    4) A name from the standard C library with external linkage. _A is not a standard C name.

    5) A function signature from the standard C library with external linkage. See item 2.

    Of course, then you have the type restrictions where any T of ::T or std::T or type from the standard C library are reserved. But _A doesn't violate this because it is neither in the global namespace, the std namespace, or the standard C library as a type.

    Therefore my code is conforming. And whether my interpretation is right or wrong, it is certainly an argument in favor of the convention to avoid leading underscores completely.
    My best code is written with the delete key.

  10. #10
    S Sang-drax's Avatar
    Join Date
    May 2002
    Location
    Göteborg, Sweden
    Posts
    2,072
    Quote Originally Posted by Prelude
    As per section 17.4.3.1, we know that the following kinds of names are reserved: Macros, global names, and names with external linkage.
    It says that the standard C++ library reserves those kind of names. Further down, we learn that the implementation has a set of names that is always reserved for it to use.
    Quote Originally Posted by C++ standard
    (17.4.3.1)
    The C++ Standard Library reserves the following kinds of names:
    The implementation could reserve more names for internal/special use:
    Quote Originally Posted by C++ standard
    17.4.3.1.2
    Certain sets of names and function signatures are always reserved to the implementation:
    Where "always reserved" means always reserved.
    Names that begin with an underscore and a capital letter are always reserved to the implementation.
    Therefore, A::_A is not legal, it is part of the set of names reserved to the implementation.

    My interpretation.
    Last edited by Sang-drax; 10-09-2004 at 08:09 PM.
    Last edited by Sang-drax : Tomorrow at 02:21 AM. Reason: Time travelling

  11. #11
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Notice the "in the global namespace" part. There are quite a few places that do not count as the global namespace
    hmm... I think that we're looking at an ambiguity in the wording of the standard.

    I interpreted that to mean that all such identifiers are reserved to the implementation, but the implementation must use them in the global namespace.
    You interpret that to mean that all such identifiers in the global namespace are reserved to the implementation.

    EDIT:
    But either way your _A must be illegal, since we're talking about all identifiers beginning with an underscore, while your example falls under the subset of all idenfifiers beginning with an underscore followed by an uppercase letter, which falls under the "for any use" rather than the "for use as a name in the global namespace" clause.
    A better example would be with _a
    Last edited by laserlight; 10-09-2004 at 11:08 PM.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  12. #12
    S Sang-drax's Avatar
    Join Date
    May 2002
    Location
    Göteborg, Sweden
    Posts
    2,072
    Quote Originally Posted by laserlight
    But either way your _A must be illegal
    [...]
    A better example would be with _a
    I absolutely agree.

    I asked Bjarne Stroustrup this question, and this is what he said:
    I'm not 100% sure, I could look it up, but why bother. People discuss the detailed formal rules and the practical implications in nausiating details, but I'd *never* use a name with a prefix underscore in C++ in user code. It's just easier to always avoid prefix _
    Last edited by Sang-drax : Tomorrow at 02:21 AM. Reason: Time travelling

  13. #13
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    Hence my point about this being a tricky area that can be interpreted multiple ways. Either could be right, but the C++ standard, in trying to be more precise, actually managed to be less precise than the C standard, which makes it perfectly clear that an underscore followed by an upper case letter is reserved in each and every situation, regardless of scope.

    I think my code is right, you think it's wrong, and there's probably an even distribution of people in the world who would agree with us because the arguments for both sides are reasonable.

    >A better example would be with _a
    A less controversial example would be with _a.

    Anyway, the debate is completely about interpretation and theory because all of us avoid leading underscores in our code. And I'm a firm believer in debates about theory being nearly useless without concrete proof. It's too bad we can't grab the person who wrote that rule and ask what was really meant just for peace of mind. There's nothing I hate more than being wrong for long periods of time.
    My best code is written with the delete key.

  14. #14
    Registered User Micko's Avatar
    Join Date
    Nov 2003
    Posts
    715
    I often find myself reading in your posts things such as according to the C++ standard or C standard. Is it possible to find FREE parts of the ISO C++ standard regarding streams. I tried google and found pdf which is 18 USD but it seems that is whole document. I'm asking for free parts of the standard not stolen goods to be precise. Thanks!

  15. #15
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    If you search google for the C or C++ draft standard, or working papers, you'll find plenty of free working papers published by the standards committees. They are close enough to the finalized standard for most purposes.
    My best code is written with the delete key.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. compare function ignoring leading white space
    By mc72 in forum C Programming
    Replies: 5
    Last Post: 11-23-2008, 01:33 PM
  2. leading zero's..... ( reading int )
    By sh4k3 in forum C Programming
    Replies: 4
    Last Post: 06-12-2007, 09:03 AM
  3. Removing Leading & Trailing Whitespace
    By EvilGuru in forum C Programming
    Replies: 11
    Last Post: 12-01-2005, 02:59 PM
  4. Converting underscores into spaces?
    By Cactus in forum C Programming
    Replies: 3
    Last Post: 09-24-2005, 12:34 PM
  5. Underscores
    By Hunter2 in forum C++ Programming
    Replies: 19
    Last Post: 09-12-2004, 03:31 PM