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

Oct 23 2008

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

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

답변

868 24revs,13users35%RogerPate Oct 23 2008 at 14:08

규칙 (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뒤에 소문자가 오는 이름 은 예약되어 있습니다.
    • 추가 문자열 및 배열 함수.
  • 소문자로 시작 PRI하거나 SCN뒤에 오는 이름 또는 X예약 된 이름
    • 추가 형식 지정자 매크로
  • 로 끝나는 이름 _t은 예약되어 있습니다.
    • 추가 유형 이름.

이러한 이름을 지금 자신의 목적으로 사용하면 문제가 발생하지 않을 수 있지만 해당 표준의 향후 버전과 충돌 할 가능성이 높아집니다.


개인적으로 나는 밑줄로 식별자를 시작하지 않습니다. 내 규칙에 대한 새로운 추가 : 밑줄을 거의 사용하지 않기 때문에 쉽게 이중 밑줄을 사용하지 마십시오.

이 기사에 대한 조사를 마친 후에 _t는 POSIX 표준에 의해 예약되어 있으므로 더 이상 식별자를 끝내지 않습니다 .

로 끝나는 식별자에 대한 규칙은 _t저를 많이 놀라게했습니다. 나는 그것이 명확하고 공식적인 장과 구절을 찾는 POSIX 표준 (아직 확실하지 않음)이라고 생각합니다. 이것은 예약 된 이름을 나열 하는 GNU libtool 매뉴얼 에서 가져온 것 입니다.

CesarB는 POSIX 2004 예약 기호 에 대한 다음 링크를 제공하고 '다른 많은 예약 된 접두사 및 접미사를 찾을 수 있습니다. POSIX 2008 예약 된 기호는 여기에 정의되어 있습니다. 제한 사항은 위의 제한 사항보다 약간 더 미묘합니다.

202 paercebal Oct 23 2008 at 14:27

이름 충돌을 방지하는 규칙은 C ++ 표준 (Stroustrup 책 참조)과 C ++ 전문가 (Sutter 등)에 의해 언급됩니다.

개인 규칙

나는 사건을 다루고 싶지 않았고 간단한 규칙을 원했기 때문에 간단하고 정확한 개인적인 규칙을 디자인했습니다 .

심볼 이름을 지정할 때 다음과 같은 경우 컴파일러 / OS / 표준 라이브러리와의 충돌을 피할 수 있습니다.

  • 밑줄로 기호를 시작하지 마십시오.
  • 내부에 두 개의 연속 된 밑줄이있는 기호의 이름을 지정하지 마십시오.

물론 코드를 고유 한 네임 스페이스에 넣으면 충돌을 피하는데도 도움이됩니다 (그러나 악의적 인 매크로로부터 보호하지는 못함).

몇 가지 예

(C / C ++ 기호의 코드 오염이 더 많기 때문에 매크로를 사용하지만 변수 이름에서 클래스 이름까지 모든 것이 될 수 있습니다)

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

C ++ 0x 초안에서 추출

로부터 n3242.pdf의 파일 (나는 유사한 것으로 최종 표준 텍스트 예상) :

17.6.3.3.2 전역 이름 [global.names]

특정 이름 및 함수 서명 집합은 항상 구현에 예약되어 있습니다.

— 이중 밑줄 _ _을 포함하거나 밑줄로 시작하고 그 뒤에 대문자 (2.12)가 오는 각 이름은 모든 용도로 구현에 예약되어 있습니다.

— 밑줄로 시작하는 각 이름은 전역 네임 스페이스에서 이름으로 사용하기 위해 구현에 예약되어 있습니다.

또한 :

17.6.3.3.5 사용자 정의 리터럴 접미사 [usrlit.suffix]

밑줄로 시작하지 않는 리터럴 접미사 식별자는 향후 표준화를 위해 예약되어 있습니다.

이 마지막 절은 하나의 밑줄로 시작하고 뒤에 소문자가 오는 이름이 전역 네임 스페이스에 정의 되지 않은 경우 Ok가된다고 생각하지 않는 한 혼란 스럽습니다 .

40 RogerLipscombe Oct 23 2008 at 14:06

에서 MSDN :

식별자 시작 부분에 두 개의 연속적인 밑줄 문자 (__)를 사용하거나 하나의 선행 밑줄 뒤에 대문자가 오는 것은 모든 범위에서 C ++ 구현을 위해 예약되어 있습니다. 현재 또는 향후 예약 된 식별자와 충돌 할 수 있으므로 파일 범위가있는 이름에 대해 하나의 선행 밑줄 다음에 소문자를 사용하지 않아야합니다.

즉, 뒤에 소문자가 오는 한 단일 밑줄을 멤버 변수 접두사로 사용할 수 있습니다.

이것은 C ++ 표준의 섹션 17.4.3.1.2에서 가져온 것으로 보이지만 온라인에서 전체 표준에 대한 원본 소스를 찾을 수 없습니다.

이 질문을 참조하십시오 .

25 MaxLybbert Nov 15 2008 at 03:03

질문의 다른 부분에 관해서 는 변수 이름 끝에 밑줄을 넣어 내부와 충돌하지 않는 것이 일반적 입니다.

클래스와 네임 스페이스 내에서도이 작업을 수행합니다. 그 다음에는 하나의 규칙 만 기억하면됩니다 ( "전역 범위에서 이름의 끝에서, 다른 곳에서는 이름의 시작"과 비교).

1 JohnMillikin Oct 23 2008 at 14:05

예, 밑줄은 식별자의 어디에서나 사용할 수 있습니다. 규칙은 첫 번째 문자의 az, AZ, _ 및 다음 문자의 경우 + 0-9입니다.

밑줄 접두사는 C 코드에서 일반적입니다. 단일 밑줄은 "비공개"를 의미하고 이중 밑줄은 일반적으로 컴파일러에서 사용하도록 예약되어 있습니다.