서명되지 않은 long int를 사용하는 경우에도 오버플로가 나타납니다.
다음과 같은 계산을 할 때:
unsigned long long int data_size = 60123456 * 128 * sizeof(double);
printf("data_size= %llu \n", data_size);
놀랍게도 오버플로 경고를 받습니다.
test.c:20:49: warning: overflow in expression; result is -894132224 with type 'int' [-Winteger-overflow]
unsigned long long int data_size = 60123456 * 128 * sizeof(double);
^
1 warning generated.
사용하고 있는데도 왜 이 오류가 나타나는지 이해할 수 없습니다.unsigned long long int
! 누가 왜 그런지 설명해 줄 수 있나요?감사해요.
값이 변수에 할당되기 전에 오버플로가 발생합니다.이를 방지하려면 긴 접미사를 사용합니다.
60123456LL * 128 * sizeof(double)
(설명에 따르면 ULL은 값이 서명된 범위 내에 있기 때문에 여기서 필요하지 않지만 일반적으로 사용할 수 있는 방법은 다음과 같습니다.
당신은 너무 늦게 "롱 롱"으로 전환하고 있습니다.60123456 * 128
여전히 넘치는 int 표현입니다.
해라60123456LL * 128
대신.(LL은 결과값이 긴 시간 안에 들어갈 것을 보장하지 않기 때문입니다.)
unsigned long long int data_size = 60123456 * 128 * sizeof(double); // trouble-some code
대상 유형unsigned long long int data_size =
제품 계산과 무관함60123456 * 128 * sizeof(double)
.
오버플로를 방지하기 위해 최소한 대상 유형의 크기를 사용하여 연산을 수행하도록 하는 것이 가장 좋습니다.OP의 경우, 그것은 다음과 같은 상수를 의미합니다.LLU
.
두 가지 제품 계산이 있으며, 각각 고유한 유형의 수학이 있습니다.
60123456
가int
아니면long
에 따라int
범위입니다. 예를 들어 다음과 같이 가정해 보겠습니다.int
.
60123456 * 128
가int * int
. 수학제품을7695802368
32비트 서명 정수 범위를 초과하므로 32비트의 서명 정수 오버플로 또는 UB(정의되지 않은 동작)가 됩니다.int
.
한다면60123456 * 128
오버플로되지 않았다고 64비트가 말합니다.int
, 다음 곱셈보다* sizeof(double);
이러저러한int * size_t
결과적으로 A가 됩니다.size_t
활자 제품
제품 계산은 적어도 사용해야 합니다.unsigned long long
수학은 다음과 같습니다.
unsigned long long int data_size = 1LLU * 60123456 * 128 * sizeof(double);
// or
unsigned long long int data_size = 60123456LLU * 128 * sizeof(double);
// or
unsigned long long int data_size = 60123456;
data_size *= 128 * sizeof(double);
// or avoiding naked magic numbers
#define A_HEIGHT 60123456
#define A_WIDTH 128
unsigned long long int data_size = 1LLU * A_HEIGHT * A_WIDTH * sizeof(double);
그sizeof (double)
코드가 어떤 2D와 같은 구조의 크기를 찾으려고 시도하고 있음을 암시합니다.저는 다음과 같은 코드를 기대합니다.다음의 결과 유형을 주목합니다.sizeof
가size_t
, 그래서 제품 수학은 적어도 사용해서 완성됩니다.size_t
수학.
size_t data_size = sizeof(double) * 60123456 * 128;
printf("data_size= %zu\n", data_size);
참고 항목C에 1,000,000,000을 1000*1000으로 쓰는 이유 및 해당 세부 정보를 보려면 1000*1000*1000을 사용하지 않는 내 답변 이유.
상수들은60123456
그리고.128
활자의int
, 그러므로 그 표현은60123456 * 128
또한 유형입니다.int
. 이 식의 값은 다음 식의 범위를 오버플로합니다.int
. 이 경우 두 피연산자가 모두 상수이기 때문에 컴파일러가 탐지할 수 있습니다.
당신은 사용해야 합니다.ULL
첫 번째 피연산자에서 접미사를 사용하여 상수의 유형을 만듭니다.unsigned long long
. 이렇게 하면 할당된 유형과 일치합니다.그러면 이 값을 포함하는 모든 연산에 대해 다른 피연산자는 다음으로 승격됩니다.unsigned long long
작업이 적용되기 전에 오버플로우가 발생하지 않을 것입니다.
따라서 결과식은 다음과 같이 나타납니다.
unsigned long long int data_size = 60123456ULL * 128 * sizeof(double);
사전 을 C 7(을 C ) cf ISO9899 합니다 합니다.5.1.1.2 Translation phases
다른 에 , 와 같은 .int
unsigned long long
대로, 그리고,해.default arithmetic conversions
합니다.unsigned long long
.unsigned long long
에로부터 에.*
다를 으로써 말이죠. 그래서 글을 쓰는 것으로.60123456ULL * 128
아니면60123456 * 128ULL
혹은 둘 다.
언급URL : https://stackoverflow.com/questions/45281718/overflow-appears-even-when-using-unsigned-long-int
'sourcetip' 카테고리의 다른 글
AngularJS - 경로 간 데이터 저장 (0) | 2023.10.15 |
---|---|
구조 vs.범위의 함수 정의 (0) | 2023.10.15 |
2011년에 자바스크립트 date.getYear()가 111을 반환한다고요? (0) | 2023.10.10 |
PowerShell에서 익명 개체를 만들려면 어떻게 해야 합니까? (0) | 2023.10.10 |
EntityManager.createNativeQuery가 페이지화를 사용할 때 BigDecimal 목록 대신 개체 목록을 반환합니다. (0) | 2023.10.10 |