sourcetip

서명되지 않은 long int를 사용하는 경우에도 오버플로가 나타납니다.

fileupload 2023. 10. 15. 17:33
반응형

서명되지 않은 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.


두 가지 제품 계산이 있으며, 각각 고유한 유형의 수학이 있습니다.

60123456int아니면long에 따라int범위입니다. 예를 들어 다음과 같이 가정해 보겠습니다.int.

60123456 * 128int * int. 수학제품을769580236832비트 서명 정수 범위를 초과하므로 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와 같은 구조의 크기를 찾으려고 시도하고 있음을 암시합니다.저는 다음과 같은 코드를 기대합니다.다음의 결과 유형을 주목합니다.sizeofsize_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다른 에 , 와 같은 .intunsigned 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

반응형