code

기본적으로 int가 아닌 정수 리터럴 유형?

starcafe 2023. 8. 26. 12:00
반응형

기본적으로 int가 아닌 정수 리터럴 유형?

저는 방금 이 질문에 답했습니다. 이 질문은 for 루프에서 100억까지 반복하는 것이 10억까지 반복하는 것보다 왜 그렇게 오래 걸리느냐는 질문이었습니다.

for (i = 0; i < 10000000000; i++)

저와 다른 많은 사람들의 분명한 대답은 반복 변수가 32비트(100억에 도달하지 않음)이고 루프가 무한 루프를 얻기 때문이라는 것이었습니다.

하지만 저는 이 문제를 깨달았지만, 여전히 컴파일러 내부에서 실제로 무슨 일이 일어나고 있는지 궁금합니다.

리터럴에 다음이 추가되지 않았기 때문입니다.L는 IMHO 타입이어야 .int32비트도 마찬가지입니다.따라서 오버플로로 인해 정상이어야 합니다.int도달할 수 있는 범위 내에 있습니다.에서 도달할 수 없다는 것을 실제로 인식하는 것.int컴파일러는 그것이 100억이라는 것을 알아야 하며 따라서 그것을 32비트 이상의 상수로 보아야 합니다.

(이에는 적어도 됩니까?L그리고 이것이 표준적인 행동입니까?아니면 오버플로(정수 오버플로가 실제로는 UB인가)로 인해 UB와 같은 배후에서 뭔가 다른 일이 일어나고 있습니까?이 기준서의 일부 인용문이 있으면 좋을 수도 있습니다.

원래 질문은 C였지만, C++ 답변도 감사합니다.

C++에 관한 한:

C++11, [lex.icon] 2

정수 리터럴의 유형은 표 6에서 해당 값을 나타낼 수 있는 목록 중 첫 번째입니다.

그리고 표 6은 접미사와 십진 상수가 없는 리터럴의 경우 다음을 제공합니다.

int
long int
long long int

또는 의 경우에도 (16진수, 16진수 8진수)unsigned형식은 허용되지만 각 형식은 목록에서 해당 서명된 형식 다음에 옵니다.)

그래서, 그 경우에 상수는 다음과 같이 해석된 것이 분명합니다.long int(또는)long long int한다면long int너무 32비트였습니다.).

"너무 큰 리터럴"은 컴파일 오류를 초래합니다.

프로그램의 변환 단위 중 하나에 허용된 형식으로 나타낼 수 없는 정수 리터럴이 포함된 경우 프로그램의 형식이 잘못되었습니다.

(ibidem, 3)

샘플에서 즉시 확인할 수 있으며, 이는 ideone.com 이 32비트 컴파일러를 사용한다는 것을 상기시킵니다.


C에 대한 질문이었는데... 뭐, 거의 비슷하네요.

C99, § 6.4.4.1

정수 상수의 유형은 해당 값이 표시될 수 있는 목록 중 첫 번째입니다.

C++ 표준과 동일한 목록입니다.


부록: C99와 C++11 모두 리터럴이 다른 모든 것이 실패할 경우 "확장 정수 유형"(즉, 다른 구현 특정 정수 유형)이 되도록 허용합니다. (C++11, [lex.icon] 3; C99, 표 뒤에 § 6.4.4.15)

ISO/IEC 9899라는 라벨이 붙은 C 표준 초안에서:TC2 위원회 초안 — 2005년 5월 6일, 규칙은 Matteo가 발견한 C++ 규칙과 매우 유사합니다.

5 정수 상수의 유형은 그 값이 표현될 수 있는 해당 목록의 첫 번째입니다.

Suffix      Decimal Constant          Octal or Hexadecimal Constant
-------------------------------------------------------------------
none        int                       int
            long int                  unsigned int
            long long int             long int
                                      unsigned long int
                                      long long int
                                      unsigned long long int

u or U      unsigned int              unsigned int
            unsigned long int         unsigned long int
            unsigned long long int    unsigned long long int

l or L      long int                  long int
            long long int             unsigned long int
                                      long long int
                                      unsigned long long int
Both u or U unsigned long int         unsigned long int
and l or L  unsigned long long int    unsigned long long int

ll or LL    long long int             long long int
                                      unsigned long long int

Both u or U unsigned long long int    unsigned long long int
and ll or LL 

나는 여전히 컴파일러 내부에서 실제로 무슨 일이 일어나고 있었는지 궁금합니다.

컴파일러가 코드를 해석하는 방법에 관심이 있다면 어셈블리어를 볼 수 있습니다.

10000000000:

400054f:
mov    -0x4(%rbp),%eax
mov    %eax,-0x8(%rbp)
addl   $0x1,-0x4(%rbp)
jmp    40054f <main+0xb>

그래서 10000000000을 1000000으로 바꾸면 무한 루프로 컴파일했습니다.

....
test   %al,%al
jne    400551

언급URL : https://stackoverflow.com/questions/8108642/type-of-integer-literals-not-int-by-default

반응형