developer tip

C ++ 식별자에서 밑줄을 사용하는 규칙은 무엇입니까?

copycodes 2020. 9. 28. 09:18
반응형

C ++ 식별자에서 밑줄을 사용하는 규칙은 무엇입니까?


C ++에서는 멤버 변수에 어떤 종류의 접두사로 이름을 지정하여 지역 변수 나 매개 변수가 아니라 멤버 변수라는 사실을 나타내는 것이 일반적입니다. MFC 배경에서왔다면 아마도 m_foo. 나는 또한 myFoo가끔 보았다 .

C # (또는 .NET)은 .NET과 같이 밑줄 만 사용하는 것이 좋습니다 _foo. 이것이 C ++ 표준에서 허용됩니까?


규칙 (C ++ 11에서는 변경되지 않음) :

  • 구현 매크로 사용을 포함하여 모든 범위에서 예약됩니다 .
    • 밑줄로 시작하고 바로 뒤에 대문자가 오는 식별자
    • 인접한 밑줄 (또는 "이중 밑줄")을 포함하는 식별자
  • 글로벌 네임 스페이스에 예약 됨 :
    • 밑줄로 시작하는 식별자
  • 또한 std네임 스페이스의 모든 것이 예약되어 있습니다. (하지만 템플릿 전문화를 추가 할 수 있습니다.)

2003 C ++ 표준에서 :

17.4.3.1.2 전역 이름 [lib.global.names]

특정 이름 및 함수 서명 세트는 항상 구현에 예약되어 있습니다.

  • 이중 밑줄 ( __)을 포함하거나 밑줄로 시작하고 그 뒤에 대문자 (2.11)가 오는 각 이름 은 모든 용도로 구현에 예약되어 있습니다.
  • 밑줄로 시작하는 각 이름은 전역 네임 스페이스에서 이름으로 사용하기 위해 구현에 예약되어 있습니다. 165

165) 이러한 이름은 네임 스페이스 ::std(17.4.3.1) 에도 예약되어 있습니다 .

C ++는 C 표준 (1.1 / 2, C ++ 03)을 기반으로하고 C99는 표준 참조 (1.2 / 1, C ++ 03)이므로 1999 C 표준에서도 적용됩니다.

7.1.3 예약 식별자

각 헤더는 관련 하위 절에 나열된 모든 식별자를 선언하거나 정의하고, 선택적으로 모든 용도 또는 파일 범위 식별자로 사용하기 위해 항상 예약 된 관련 미래 라이브러리 지침 하위 절에 나열된 식별자를 선언하거나 정의합니다.

  • 밑줄과 대문자 또는 다른 밑줄로 시작하는 모든 식별자는 항상 모든 용도로 예약되어 있습니다.
  • 밑줄로 시작하는 모든 식별자는 항상 일반 및 태그 이름 공간 모두에서 파일 범위가있는 식별자로 사용하도록 예약되어 있습니다.
  • 다음 하위 절 (향후 라이브러리 지침 포함)의 각 매크로 이름은 연관된 헤더가 포함 된 경우 지정된대로 사용하도록 예약되어 있습니다. 달리 명시되지 않는 한 (7.1.4 참조).
  • 다음 하위 절 (향후 라이브러리 지침 포함)에서 외부 연결이있는 모든 식별자는 항상 외부 연결이있는 식별자로 사용하도록 예약되어 있습니다. 154
  • 다음 하위 절 (향후 라이브러리 지침 포함)에 나열된 파일 범위를 가진 각 식별자는 매크로 이름 및 관련 헤더가 포함 된 경우 동일한 이름 공간에서 파일 범위가있는 식별자로 사용하도록 예약되어 있습니다.

다른 식별자는 예약되지 않습니다. 프로그램이 예약 된 컨텍스트에서 식별자를 선언 또는 정의하거나 (7.1.4에서 허용하는 경우 제외) 예약 된 식별자를 매크로 이름으로 정의하는 경우 동작은 정의되지 않습니다.

프로그램이 #undef위에 나열된 첫 번째 그룹에서 식별자의 매크로 정의를 제거하면 (사용하여 ) 동작이 정의되지 않습니다.

154) 외부 링크 예약 식별자리스트가 포함되어 errno, math_errhandling, setjmp, 및 va_end.

다른 제한 사항이 적용될 수 있습니다. 예를 들어, POSIX 표준은 일반 코드에 나타날 가능성이 높은 많은 식별자를 예약합니다.

  • E대문자로 시작하는 이름 뒤에 숫자 또는 대문자가 이어집니다.
    • 추가 오류 코드 이름에 사용될 수 있습니다.
  • 소문자로 시작 is하거나 to뒤에 오는 이름
    • 추가 문자 테스트 및 변환 기능에 사용할 수 있습니다.
  • LC_대문자로 시작하는 이름
    • 로케일 속성을 지정하는 추가 매크로에 사용할 수 있습니다.
  • 접미사 f또는 l예약 된 모든 기존 수학 함수의 이름
    • 각각 float 및 long double 인수에서 작동하는 해당 함수의 경우.
  • SIG대문자로 시작하는 이름 은 예약되어 있습니다.
    • 추가 신호 이름.
  • SIG_대문자로 시작하는 이름 은 예약되어 있습니다.
    • 추가 신호 조치를 위해.
  • str,로 시작 mem하거나 wcs뒤에 소문자가 오는 이름 은 예약되어 있습니다.
    • 추가 문자열 및 배열 함수.
  • Names beginning with PRI or SCN followed by any lowercase letter or X are reserved
    • for additional format specifier macros
  • Names that end with _t are reserved
    • for additional type names.

While using these names for your own purposes right now might not cause a problem, they do raise the possibility of conflict with future versions of that standard.


Personally I just don't start identifiers with underscores. New addition to my rule: Don't use double underscores anywhere, which is easy as I rarely use underscore.

After doing research on this article I no longer end my identifiers with _t as this is reserved by the POSIX standard.

The rule about any identifier ending with _t surprised me a lot. I think that is a POSIX standard (not sure yet) looking for clarification and official chapter and verse. This is from the GNU libtool manual, listing reserved names.

CesarB provided the following link to the POSIX 2004 reserved symbols and notes 'that many other reserved prefixes and suffixes ... can be found there'. The POSIX 2008 reserved symbols are defined here. The restrictions are somewhat more nuanced than those above.


The rules to avoid collision of names are both in the C++ standard (see Stroustrup book) and mentioned by C++ gurus (Sutter, etc.).

Personal rule

Because I did not want to deal with cases, and wanted a simple rule, I have designed a personal one that is both simple and correct:

When naming a symbol, you will avoid collision with compiler/OS/standard libraries if you:

  • never start a symbol with an underscore
  • never name a symbol with two consecutive underscores inside.

Of course, putting your code in an unique namespace helps to avoid collision, too (but won't protect against evil macros)

Some examples

(I use macros because they are the more code-polluting of C/C++ symbols, but it could be anything from variable name to class name)

#define _WRONG
#define __WRONG_AGAIN
#define RIGHT_
#define WRONG__WRONG
#define RIGHT_RIGHT
#define RIGHT_x_RIGHT

Extracts from C++0x draft

From the n3242.pdf file (I expect the final standard text to be similar):

17.6.3.3.2 Global names [global.names]

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

But also:

17.6.3.3.5 User-defined literal suffixes [usrlit.suffix]

Literal suffix identifiers that do not start with an underscore are reserved for future standardization.

This last clause is confusing, unless you consider that a name starting with one underscore and followed by a lowercase letter would be Ok if not defined in the global namespace...


From MSDN:

Use of two sequential underscore characters ( __ ) at the beginning of an identifier, or a single leading underscore followed by a capital letter, is reserved for C++ implementations in all scopes. You should avoid using one leading underscore followed by a lowercase letter for names with file scope because of possible conflicts with current or future reserved identifiers.

This means that you can use a single underscore as a member variable prefix, as long as it's followed by a lower-case letter.

This is apparently taken from section 17.4.3.1.2 of the C++ standard, but I can't find an original source for the full standard online.

See also this question.


As for the other part of the question, it's common to put the underscore at the end of the variable name to not clash with anything internal.

I do this even inside classes and namespaces because I then only have to remember one rule (compared to "at the end of the name in global scope, and the beginning of the name everywhere else").


Yes, underscores may be used anywhere in an identifier. I believe the rules are: any of a-z, A-Z, _ in the first character and those + 0-9 for following characters.

Underscore prefixes are common in C code -- a single underscore means "private", and double underscores are usually reserved for use by the compiler.

참고URL : https://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier

반응형