C / C ++에서 long long


84

GNU의 C ++ 컴파일러에서이 코드를 시도하고 있는데 그 동작을 이해할 수 없습니다.

#include <stdio.h>;

int main()
{
    int  num1 = 1000000000;
    long num2 = 1000000000;
    long long num3;
    //num3 = 100000000000;
    long long num4 = ~0;

    printf("%u %u %u", sizeof(num1), sizeof(num2), sizeof(num3));
    printf("%d %ld %lld %llu", num1, num2, num3, num4);
    return 0;
}

주석 처리 된 줄의 주석 처리를 제거하면 코드가 컴파일되지 않고 오류가 발생합니다.

오류 : 정수 상수가 long 유형에 비해 너무 큽니다.

그러나 코드가있는 그대로 컴파일되고 실행되면 10000000000보다 훨씬 큰 값이 생성됩니다.

왜?


8
지금은 너무 늦을 수 있지만 미래의 독자를 위해를 사용 <stdint.h>하고 사용하는 것이 좋습니다 uint64_t. 64 비트 값을 표시하려면printf( "%" PRIu64 "\n", val);
열광적 인 매니아 인

@enthusiasticgeek <stdint.h>포함,uint64_t a = 0xffffffffffffff; printf( "%" PRIu64 "\n",a ); : error: expected ‘)’ before ‘PRIu64’ printf( "%" PRIu64 "\n",a ); :: warning: spurious trailing ‘%’ in format [-Wformat=] printf( "%" PRIu64 "\n",a );
Herdsman

답변:


147

문자 100000000000은 리터럴 정수 상수를 구성하지만 값이 유형에 비해 너무 큽니다 int. 리터럴의 유형을 변경하려면 접미사를 사용해야합니다.

long long num3 = 100000000000LL;

접미사 LL는 리터럴을 유형으로 만듭니다 long long. C는 왼쪽의 유형에서 결론을 내리기에 충분히 "스마트"하지 않습니다. 유형은 사용되는 컨텍스트가 아니라 리터럴 자체의 속성입니다.


47
돌아 가기이 답변이 작성되었을 때 아마 정확했다,하지만 지금은 C ++ 표준이없는 접미사 정수 리터럴의 유형 중 첫 번째 것을 말한다 int, long int하고 long long int있는 그 값이 표현 될 수있다. [C ++ §2.14.2 / 2] 따라서 이제 다른 유형에 비해 너무 큰 정수 리터럴에 'LL'접미사를 추가 할 필요가 없습니다.
bames53

8
이것이 이전에 문제가 된 이유는 C ++가 할당되는 변수의 유형에서 리터럴 유형을 결정할만큼 '스마트'하지 않았기 때문이 아니라 단순히 컴파일러 확장이 확장 정수를 구현하지 않았기 때문일 것입니다. 표준 언어와 잘 작동하도록 입력하십시오. C ++에는 이제 확장 된 정수 유형이 표준과 더 잘 통합되는 규칙이 있습니다. open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1988.pdf
bames53

4
@unwind이 제안에 따라 답변을 편집해야한다고 생각합니다.
Antonio


4

컴파일하는 모드에 따라 다릅니다. long long은 C ++ 표준의 일부가 아니지만 (보통) 확장으로 만 지원됩니다. 이것은 리터럴 유형에 영향을줍니다. 접미사가없는 십진 정수 리터럴은 int가 숫자를 나타낼 만큼 충분히 크면 항상 int 유형 이고 그렇지 않으면 long입니다. 숫자가 너무 길어도 그 결과는 구현에 따라 정의됩니다 (아마도 이전 버전과의 호환성을 위해 잘린 long int 유형의 숫자 ​​일 것입니다). 이 경우 대부분의 컴파일러에서 long long 확장을 활성화하려면 LL 접미사를 명시 적으로 사용해야합니다.

다음 C ++ 버전은 리터럴의 유형이 적어도 long long이되도록 명시 적으로 원하지 않는 한 접미사가 필요하지 않은 방식으로 long long을 공식적으로 지원합니다. 숫자를 길게 표현할 수없는 경우 컴파일러는 LL 접미사 없이도 long long을 자동으로 사용하려고합니다. 나는 이것이 C99의 행동이라고 생각합니다.


1

귀하의 코드는 여기에서 잘 컴파일됩니다 (해석이없는 경우에도.

num3 = 100000000000000000000;

경고를 받기 시작합니다.


무슨 컴파일러? C ++에서 정수 리터럴은 int 중 더 작거나 맞는 long입니다. C99에서는 int, long, long long 중 가장 작은 것입니다. 따라서 비표준 확장으로 C ++에 오랫동안 추가 할 때 컴파일러는 리터럴에 대한 C99 규칙도 채택했을 것입니다.
Steve Jessop

64 비트 Linux 시스템의 gcc 버전 4.3.2 (Debian 4.3.2-1.1).
Omry Yadan

@SteveJessop 아마도 조금 늦었을 것입니다. 그러나 long이 반드시 64 비트는 아닙니다. 대부분의 경우 그렇지만 어디에나있을 것이라는 보장은 없습니다. 당신이 가진 유일한 보장은 그것이 적어도 int만큼 크다는 것입니다. 이것은 차례로 적어도 짧은 int만큼 크며, 차례로 적어도 char만큼 큽니다. 마지막으로 char은 구현의 기본 문자 집합 (일반적으로 8 비트) 모든 문자를 나타낼만큼 충분히 큰 것으로 정의됩니다 .
pauluss86 2013

@ pauluss86 : 보장에 대해 얘기 한 것이 아닙니다. Omry는 64 비트 데비안 시스템에서 gcc 4.3.2를 사용하고 있다고 말했습니다. 나는 이것이 그가 (일반적인 지식의 문제로 알고 있음) gcc가 기본적으로 long해당 OS의 LP64 ABI에 따라 64 비트를 사용하도록 구성되어 있기 때문에 그가보고있는 것을 설명하는 것을 관찰했습니다 .
Steve Jessop

@SteveJessop 나는 귀하의 의견이 잘못되었다고 제안하는 것이 아닙니다! 불행히도 많은 사람들이 생각하는 long이 항상 64 비트라는 가정은 위험하다는 점만 지적합니다.
pauluss86 2013
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.