programing

문자를 빼는 동작이 구체적인 이유는 무엇입니까?

stoneblock 2023. 6. 13. 21:56

문자를 빼는 동작이 구체적인 이유는 무엇입니까?

다음 문장:

if('z' - 'a' == 25)

동일한 방식으로 평가하는 것이 보장되지 않습니다.컴파일러에 종속되어 있습니다.또한 다음과 같은 방식으로 평가되지는 않습니다.

#if 'z' - 'a' == 25

프리프로세서와 컴파일러가 모두 동일한 시스템에서 실행되는 경우에도 마찬가지입니다.왜 그런 것일까요?

OP는 표준의 직접 인용문 N1570 § 6.10.1p3,4 + 각주 168:

제어 상수 표현식은 6.6의 규칙에 따라 평가됩니다.여기에는 이스케이프 시퀀스를 실행 문자 집합 멤버로 변환하는 것이 포함될 수 있는 문자 상수 해석이 포함됩니다.이러한 문자 상수의 숫자 값이 식에서 동일한 문자 상수가 발생할 때 얻은 값과 일치하는지 여부(#if 또는 #elif 지시어 내에서 제외)는 구현 정의됩니다.168

[footnote 168] 따라서 다음과 같은 #if 지시문과 if 문이 이 두 가지 상황에서 동일한 값으로 평가될 것을 보장하지 않는 경우의 상수 식.

#if 'z' - 'a' == 25
if ('z' - 'a' == 25)

그래서, 네, 그것은 정말로 보장되지 않습니다.

보증되지 않는 이유를 이해하려면 먼저 C 표준에 문자 상수가 필요하지 않음을 알아야 합니다.'a'그리고.'z'ASCII에 의해 해당 문자에 숫자 값이 할당됩니다.오늘날 대부분의 C 구현은 ASCII 또는 슈퍼셋을 사용하지만, 여전히 널리 사용되는 EBCDIC라는 또 다른 인코딩이 있습니다(IBM 메인프레임에서만 사용되지만 여전히 많이 있습니다).EBCDIC에서 뿐만 아니라'a'그리고.'z'ASCII와 다른 값을 가집니다. 알파벳이 연속적인 시퀀스가 아닙니다!그래서 그런 표현이.'z' - 'a' == 25애초에 true로 평가되지 않을 수 있습니다.

또한 C 표준은 소스 코드에 사용되는 텍스트 인코딩("소스 문자 집합")과 프로그램이 런타임에 사용할 텍스트 인코딩("실행 문자 집합") 간의 차이를 유지하려고 합니다.따라서 적어도 원칙적으로 소스가 ASCII 텍스트로 인코딩된 프로그램을 가져와 EBCDIC을 사용하는 컴퓨터에서 수정되지 않은 상태로 실행할 수 있습니다. 소스 텍스트를 먼저 EBCDIC로 변환할 필요는 없습니다.

이제 컴파일러는 두 문자 집합이 서로 다르다면 이해해야 하지만, 역사적으로 C 프리프로세서(번역 단계 1~4)와 "컴파일러 고유"(5~7단계)는 두 개의 별개의 프로그램이었고,#if식은 사전 처리자가 실행 문자 집합에 대해 알아야 하는 유일한 위치입니다.따라서 프리프로세서가 사용하는 "실행 문자 집합"이 컴파일러가 사용하는 문자 집합과 적절한지 여부를 구현 정의함으로써, 표준은 프리프로세서가 소스 문자 집합에서 모든 작업을 수행하도록 라이센스를 부여하여 1989년 당시의 삶을 조금 더 쉽게 만들었습니다.

이 모든 것을 말했지만, 저는 실행과 소스 문자 집합이 완전히 호환되지 않는 경우에도 두 표현식을 동일한 값으로 평가하지 않는 현대의 컴파일러를 발견하면 매우 놀랄 것입니다.현대의 컴파일러는 통합된 프리프로세서를 갖는 경향이 있습니다. 1단계부터 7단계까지 모두 동일한 프로그램에 의해 수행됩니다. 그리고 그렇지 않더라도 프리프로세서를 컴파일러에 적합한 실행 문자 집합과 일치하도록 전문화해야 하는 엔지니어링 부담은 오늘날 미미합니다.

모든 컴퓨터가 아스키 또는 유니코드를 사용하는 것은 아니기 때문입니다.

과거에는, ebcdic이라고 불리는 표준이 흔했습니다.에서 ebcdic 500의 은 다음과 .'z'은 169µm입니다.'a'130입니다.그표은라는 'z'-'a'그러면 39로 평가될 것입니다.

이것은 당신이 유형의 표현식에 대해 특정 값을 가정할 수 없는 이유를 설명합니다.'a'아니 심지어는'z'-'a'그러나 Q의 두 표현식이 동일하다고 보장되지 않는 이유는 설명하지 않습니다.

프리프로세서와 컴파일러는 서로 다릅니다.프리프로세서는 소스 코드에 사용되는 인코딩을 처리하는 반면 컴파일러는 컴파일하려는 컴퓨터를 대상으로 합니다.자세한 설명은 zwol의 답변을 참조하십시오.

다른 정답으로 확장하자면, 여전히 사용되고 있는 ASCII가 아닌 C 컴파일러의 실제 예로는 IBM의 z/OS XL C/C++있습니다.기본적으로 소스 파일은 IBM 코드 페이지 1047(Latin-1과 동일한 레퍼토리를 가진 EBCDIC 버전)에 있다고 가정합니다.그러나 ASCII뿐만 아니라 "하이브리드 코드" 또는 둘 이상의 인코딩으로 데이터를 포함하는 소스 파일을 지원하는 여러 컴파일러 옵션이 있습니다. (MVS 컴파일러는 구문문이 IBM-1047 인코딩으로만 필요했기 때문에 이러한 프로그램이 존재합니다.)

설명서에서 볼 때 다음과 같은 명령을 사용하여 작업을 수행할 수 있습니다.#pragma CONVLIT(suspend)그 컴파일러에서 두 문장을 다르게 평가하는 방식으로.MCVE를 테스트할 복사본이 없습니다.

언급URL : https://stackoverflow.com/questions/46890093/why-is-the-behaviour-of-subtracting-characters-implementation-specific