C Интегральное переполнение? - PullRequest
8 голосов
/ 07 июля 2011

взгляните на это. Компилятор жалуется, что у меня переполнение целого числа, но когда я смотрю на правила стандарта C89 для интегрального продвижения вместе со значениями в этом выражении, мне кажется, что переполнения нет.

rutski@imac:~$ cat test.c 
#include <stdio.h>
#include <inttypes.h>

const uint32_t value =
    (0x7F-0x00 + 1) * (256 + 256*256 + 256*256*256) +
    (0xDF-0xC2 + 1) * (256 + 256*256 + 256*256*256);

int
main(void)
{
    printf("value = %"PRIu32"\n", value);
    return 0;
}
rutski@imac:~$ gcc -std=c89 -pedantic -Wall -Wextra test.c
test.c:5: warning: integer overflow in expression
test.c:6: warning: integer overflow in expression
test.c:6: warning: overflow in constant expression
rutski@imac:~$ ./a.out 
value = 2661195264
rutski@imac:~$ 

Кроме того, Google подтверждает, что ответ 2661195264 является правильным значением для этого выражения! ( см. Ссылку )

Итак, как получается, что программа может выдавать правильное значение при переполнении целого числа? И что более важно, как получилось, что в этом выражении началось целочисленное переполнение?

Ответы [ 2 ]

14 голосов
/ 08 июля 2011
(0x7F-0x00 + 1) * (256 + 256*256 + 256*256*256)

имеет значение 2155905024;наибольшее представимое значение со знаком 32-разрядное int равно 2147483647, поэтому вы действительно произвели переполнение.Так или иначе, он дал вам ожидаемый результат (вам повезло).

Обратите внимание, что весь ваш инициализатор имеет тип подписанный (в частности, тип int), поскольку ни один из литераловимеют суффиксВыражение оценивается как int со знаком, затем полученное значение преобразуется в целое число без знака.

2 голосов
/ 08 июля 2011

Хотя все ваши константы положительны, они все равно являются целыми числами со знаком. Вы переполняете диапазон целого числа со знаком. Результат преобразуется в неподписанный как последний шаг, если он назначен переменной.

Битовые комбинации для сложения, вычитания и умножения идентичны для операций со знаком и без знака. Хотя компилятор не обязан предоставлять правильный ответ в этом случае, это просто самый естественный результат.

...