본문 바로가기

StackOverflow

[C] ??!??! 연산자가 무슨 의미인가요?

http://stackoverflow.com/questions/7825055/what-does-the-c-operator-do


Q: ??!??! 연산자가 무엇인가요?

아래와 같은 C코드 한 라인를 보았습니다.

!ErrorHasOccured() ??!??! HandleError();

이 코드는 정상적으로 컴파일이 되었고, 실행도 잘 되었습니다. 에러가 났는지 체크를 하고, 만약 에러가 났다면 그걸 처리하는 코드 같습니다. 하지만 이게 진짜로 무슨 뜻인지, 아니 그보다 이게 이런 코드가 동작하는지 이해가 안됩니다. 마치 개발자가 이 에러를 만났을 때의 기분을 표현한 코드처럼 보일 지경입니다.

저는 ??!??!연산자를 한 번도 본적이 없고, 다른 언어에서도 마찬가지로 못봤습니다. 그리고 이와 관련된 문서도 전혀 찾아볼 수가 없었습니다. (구글로는 특수기호로 인식이 되어 검색이 안됩니다) 이 연산자의 역할이 무엇이고, 이 코드는 어떤 동작을 하는 코드인가요?


(질문자: Peter Olson)


A: ??!은 trigraph이고, |으로 변환됩니다. 그래서 아래 코드는 이런 의미입니다.

!ErrorHasOccured() || HandleError();
이것도 줄여놓은 코드인데, 풀어서 쓰면 아래와 같은 뜻입니다.
if (ErrorHasOccured())
    HandleError();

Guru of the Week(C++을 다루는 곳이지만, 이 질문과 연관있음)에서 발견했습니다.

Possible origin of trigraphs 또는 @DwB 가 남긴 댓글에 따르면, EBCDIC 인코딩 방식 때문인 것 같습니다. IBM 개발자 사이트의 이 토론에서 근거를 확인할 수 있습니다.

ISO/IEC 9899:1999 5.2.1,1 각주 12 (h/t @Random832)

trigraph는 ISO/IEC 646에 정의된 것 처럼, 특정 글자가 정의되지 않은 경우에 이용된다. 이는 미국의 7비트 ASCII 코드 셋의 하위 집합인 경우에 해당된다.

(답변자: user786653)


A: C언어와 UNIX의 초창기 시절에 많이 쓰이던 ASR-33 텔레타이프 장치에서 쓰이던 거네요.

이 장치는 느리고 (10 cps) 시끄럽고 못생겼고, ASCII 캐릭터 셋이 0x5F에서 끝나버리기 때문에 아래와 같은 기호는 입력할 수가 없었습니다.

{ | } ~ 

이 trigraph라는 것은 ASR-33 텔레타이프 장치같은, ASCII 코드 중 일부(나중에 나오는 부분)이 존재하지 않는 기기를 위해 만들어진 겁니다.


(답변자: DigitalRose)


_

I saw a line of C that looked like this:

!ErrorHasOccured() ??!??! HandleError();

It compiled correctly and seems to run ok. It seems like it's checking if an error has occurred, and if it has, it handles it. But I'm not really sure what it's actually doing or how it's doing it. It does look like the programmer is trying express their feelings about errors.

I have never seen the ??!??! before in any programming language, and I can't find documentation for it anywhere. (Google doesn't help with search terms like ??!??!). What does it do and how does the code sample work?

shareeditflag

_

917down voteaccepted

??! is a trigraph that translates to |. So it says:

!ErrorHasOccured() || HandleError();

which, due to short circuiting, is equivalent to:

if (ErrorHasOccured())
    HandleError();

Guru of the Week (deals with C++ but relevant here), where I picked this up.

Possible origin of trigraphs or as @DwB points out in the comments it's more likely due to EBCDIC being difficult (again). This discussion on the IBM developerworks board seems to support that theory.

From ISO/IEC 9899:1999 §5.2.1.1, footnote 12 (h/t @Random832):

The trigraph sequences enable the input of characters that are not defined in the Invariant Code Set as described in ISO/IEC 646, which is a subset of the seven-bit US ASCII code set.

shareeditflag


_

A very common user terminal from the initial Unix and C era was the ASR-33 Teletype.

This device was slow (10 cps) and noisy and ugly and its view of the ASCII character set ended at 0x5f, so it had none of the keys:

{ | } ~ 

The trigraphs were defined so that C programs could use the ASCII subset found on the ASR-33 and in other environments missing the high ASCII values.

shareeditflag