Подтвердить что ты не робот

Является ли переполнение intN_t корректным?

В C99 существуют некоторые (необязательные) типы, такие как int8_t, int16_t и т.п., которые гарантированно имеют точно указанную ширину и не имеют битов заполнения и представляют числа в двух дополнениях (7.18.1.1), В 6.2.6.2 подписанное целочисленное переполнение упоминается как сноски 44) и 45), а именно, что это может привести к улавливанию значений в битах заполнения.

Поскольку intN_t не имеют каких-либо битов заполнения, и они гарантированно являются двумя дополнениями, означает ли это, что их переполнение не генерирует никакого поведения undefined? Что было бы результатом, например, переполненное умножение? Как насчет добавления? Является ли результат уменьшенным по модулю 2^N как для неподписанных типов?

4b9b3361

Ответ 1

Сноски не являются нормативными. Если в сноске указано, что переполнение может привести к улавливанию значений в битах заполнения, это не совсем так, но я вижу, как это немного вводит в заблуждение. В нормативном тексте просто говорится, что поведение undefined. Размещение значений захвата в битах заполнения является одним из возможных последствий поведения undefined, но не единственного.

Нет, это не означает, что определено переполнение. Это возможно для операций с операндами intN_t/uintN_t для переполнения, а для этого переполнения результатом является поведение undefined.

Что-то вроде int8_t i = 127; ++i; не имеет UB. int8_t распространяется на целые акции, поэтому добавление выполняется так, как если бы вы написали i = (int8_t) ((int) i + 1);. Само добавление не переполняется, и преобразование обратно в int8_t создает результат, определенный реализацией.

Что-то вроде uint16_t u = 65535; u *= u; имеет UB для текущих типичных реализаций, где int имеет 32 бита знака/значения. uint16_t тоже подвержен целым акциям, поэтому умножение выполняется так, как если бы вы написали u = (uint16_t) ((int) u * (int) u);. Само перемножение переполняется, а поведение undefined.

Что-то вроде int64_t i = 9223372036854775807; ++i; имеет UB почти для всех реализаций. Само добавление переполняется.

Ответ 2

Нет, он не определен, потому что... он не определен вообще. В стандарте просто нет текста, который дал бы семантике переполнение знакового целого числа.

Не перенапрягайте термин "поведение w90" как нечто загадочное, но принимайте его в прямом смысле. Определения поведения нет, поэтому стандарт не указывает ничего, что должно произойти, и никакой переносимый код не должен полагаться на такую ​​функцию.