IT이야기

C에서 이중 밑줄(__const)은 무엇을 의미하는가?

cyworld 2022. 5. 13. 23:53
반응형

C에서 이중 밑줄(__const)은 무엇을 의미하는가?

extern int ether_hostton (__const char *__hostname, struct ether_addr *__addr)
 __THROW;

Linux 박스의 /usr/include/netinet/ether.h에서 위의 함수 정의를 찾았다.

누군가가 const(키워드), addr(식별자) 및 __DOSOW 앞에서 이중 밑줄의 의미를 설명할 수 있는가?

C에서 대문자 또는 다른 밑줄 뒤에 밑줄로 시작하는 기호는 구현을 위해 남겨진다.C의 사용자로서 예약된 시퀀스로 시작하는 기호를 작성해서는 안 된다.C++에서는 제한이 더 엄격하므로 사용자는 더블 언더코어가 포함된 기호를 만들 수 없다.

주어진:

extern int ether_hostton (__const char *__hostname, struct ether_addr *__addr)
__THROW;

__const표기법은 이 코드가 사용된 컴파일러가 프로토타입 표기를 지원하지만 C89 표준 키워드를 정확하게 이해하지 못할 가능성(일부 가능성이 희박함)을 허용하기 위해 존재한다.const . The . The.autoconf매크로는 컴파일러가 다음 작업을 지원하는지 여부를 계속 확인할 수 있다.const; 이 코드는 그러한 지원이 없는 고장 난 컴파일러와 함께 사용될 수 있다.

의 사용__hostname그리고__addr헤더의 사용자인 귀하를 위한 보호 조치.GCC 및 를 사용하여 컴파일할 경우-Wshadow옵션, 컴파일러는 로컬 변수가 글로벌 변수를 음영할 때 경고한다.함수가 사용되는 경우hostname대신에__hostname, 그리고 만약 당신이 불리는 기능을 가지고 있다면.hostname()그그자가 implementation 구현에 으로써, 하지 않는다구현에 예약된 이름을 사용하면 합법적인 코드와 충돌하지 않는다.

의 사용__THROW어떤 상황에서는 코드를 일종의 '던지기 사양'으로 선언할 수 있음을 의미한다.이것은 표준 C가 아니다; 그것은 C++에 가깝다.그러나 헤더(또는 컴파일러 자체) 중 하나가 정의되는 한 C 컴파일러와 함께 코드를 사용할 수 있다.__THROW비우거나 표준 C 구문의 컴파일러 특정 확장에 사용.


C 표준의 섹션 7.1.3 (ISO 9899:1999)은 다음과 같이 말하고 있다.

7.1.3 예약된 식별자

각 헤더는 관련 하위 절에 나열된 모든 식별자를 선언하거나 정의하며, 선택적으로 연관된 미래 라이브러리 방향 하위 절과 파일 범위 식별자로 항상 예약되어 있는 식별자를 선언하거나 정의한다.

— 밑줄과 대문자 또는 다른 밑줄로 시작하는 모든 식별자는 항상 사용할 수 있도록 예약되어 있다.

— 밑줄로 시작하는 모든 식별자는 항상 일반 및 태그 이름 공간 모두에서 파일 범위가 있는 식별자로 사용할 수 있도록 예약되어 있다.

— 다음 하위 절 중 하나에 있는 매크로 이름(미래 라이브러리 지침 포함)은 별도로 명시되지 않는 한 관련 머리글이 포함된 경우 지정된 대로 사용하도록 예약된다(7.1.4 참조).

— 다음 하위 절 중 하나에 외부 연계가 있는 모든 식별자(미래 라이브러리 방향 포함)는 항상 외부 연계가 있는 식별자로 사용하도록 예약되어 있다.154)

— 다음 하위 절 중 하나에 나열된 파일 범위를 가진 각 식별자(미래 라이브러리 방향 포함)는 연관된 머리글이 포함된 경우 매크로 이름 및 동일한 이름 공간에 파일 범위를 가진 식별자로 사용하기 위해 예약된다.

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

프로그램이 제거되는 경우(포함)#undef된 첫 되지 않음 위에 나열된 첫 번째 그룹의 식별자에 대한 매크로 정의, 동작은 정의되지 않는다.

각주 154) 외부 연결이 있는 예약된 식별자 목록에는 다음이 포함된다.errnomath_errhandlingsetjmp그리고va_end.


또한 C++ 식별자에 밑줄을 사용하는 규칙은 무엇인가? 이 답변의 상단에 언급된 바와 같이 내장된 이중 언더코어 규칙이 C++에만 있지만 많은 동일한 규칙이 C와 C++ 모두에 적용된다.


C99 이론적 근거

C99 논거에 따르면 다음과 같다.

7.1.3 예약된 식별자

라이브러리 함수를 파일로 포장할 때 구현자에게 최대 관용도를 제공하기 위해, 라이브러리에 의해 정의된 모든 외부 식별자는 호스트 환경에서 예약된다.이는 사실상 사용자 기능이 동일한 규격을 가지고 있더라도 사용자가 제공한 외부 이름이 라이브러리 이름과 일치할 수 없다는 것을 의미한다.따라서 예를 들어,strtod와 동일한 객체 모듈에서 정의될 수 있음printf연결 시간 충돌이 일어날 염려 없이.마찬가지로,strtod전화해도 좋다printf또는printf전화해도 좋다strtod어떤 이유로든, 잘못된 기능이 호출될 염려가 없다.

또한 구현자를 위해 예약된 것은 밑줄로 시작하는 모든 외부 식별자와 밑줄로 시작하는 다른 모든 식별자 그리고 대문자 또는 밑줄로 시작하는 모든 식별자가 있다.이것은 수많은 비하인드 비외부 매크로를 쓸 수 있는 이름 공간을 제공하고 도서관이 제 역할을 제대로 하기 위해 필요한 기능을 제공한다.

이러한 예외를 제외하고, 이 기준서는 프로그램을 한 구현에서 다른5 구현으로 이동할 때 예기치 않은 충돌의 염려 없이 다른 식별자를 모두 사용할 수 있음을 프로그래머에게 보장한다.특히 밑줄로 시작하는 내부 식별자의 이름 공간의 일부를 사용자가 사용할 수 있다는 점에 유의하십시오. 번역기 구현자만이 "숨겨진" 이름에 사용할 수 있는 것은 아니었다.C는 여러 가지 점에서 '이름의 공간오염' 문제가 지금까지도 그랬고, 완전히 휴대할 수 있는 코드를 쓰는 데 있어 주된 장벽 중 하나이다.따라서 이 기준서는 매크로와 매크로를 보장하며typedef이름은 관련된 헤더가 명시적으로 포함된 경우에만 예약된다.

5 이행자가 이 약속을 지키기 위해 취해야 할 몇 가지 주의사항에 대한 논의는 제6.2.1조를 참조한다.또한 다음과 같이 정의된 구조에서 구현 정의 멤버 이름<time.h>그리고<locale.h>이러한 구조에서 다른 이름의 패턴을 따르기 보다는 밑줄로 시작해야 한다.

그리고 제6.2.1조 식별자 범위에 대한 근거의 관련 부분은 다음과 같다.

기능 프로토타입에서 식별자의 범위는 선언에서 시작하여 해당 기능의 선언기 끝에서 끝나지만, 이 범위는 전처리에 의해 무시된다.따라서 기존 매크로와 동일한 이름을 가진 프로토타입의 식별자는 매크로의 호출로 처리된다.예를 들면 다음과 같다.

    #define status 23
    void exit(int status);

사전 처리 후 프로토타입이 다음이 되기 때문에 오류가 발생함

   void exit(int 23);

아마도 더 놀라운 것은 상태가 정의되면 어떻게 되는가 하는 것이다.

   #define status []

Then the resulting prototype is

   void exit(int []);

which is syntactically correct but semantically quite different from the intent.

To protect an implementation’s header prototypes from such misinterpretation, the implementor must write them to avoid these surprises. Possible solutions include not using identifiers in prototypes, or using names in the reserved name space (such as __status or _Status).

See also P J Plauger The Standard C Library (1992) for an extensive discussion of name space rules and library implementations. The book refers to C90 rather than any later version of the standard, but most of the implementation advice in it remains valid to this day.

Names with double leading underscores are reserved for use by the implementation. This does not necessarily mean they are internal per se, although they often are.

The idea is, you're not allowed to to use any names starting with __, so the implementation is free to use them in places like macro expansions, or in the names of syntax extensions (e.g. __gcnew is not part of C++, but Microsoft can add it to C++/CLI confident that no existing code should have something like int __gcnew; in it that would stop compiling).

To find out what these specific extensions mean, i.e. __const you'll need to consult the documentation for your specific compiler/platform. In this particular case, you should probably consider the prototype in the documentation (e.g. http://www.kernel.org/doc/man-pages/online/pages/man3/ether_aton.3.html) to be the function's interface and ignore the __const and __THROW decorations that appear in the actual header.

By convention in some libraries, this indicates that a particular symbol is for internal use and not intended to be part of the public API of the library.

The underscore in __const means that this keyword is a compiler extension and using it is not portable (The const keyword was added to C in a later revision, 89 I think). The __THROW is also some kind of extension, I assume that it gets defined to some __attribute__(something) if gcc is used, But I'm not sure on that and too lazy to check. The __addr can mean anything the programmer wanted it to mean, It's just a name.

참조URL: https://stackoverflow.com/questions/1449181/what-does-double-underscore-const-mean-in-c

반응형