I ++ вызывает неопределенное поведение для подписанных типов, меньших, чем int, в случае переполнения?

Кажется очевидным, что следующий код вызывает неопределенное поведение из-за арифметического переполнения:

#include <limits.h>

int test(void) {
    int i = INT_MAX;
    i++;  /* undefined behavior */
    return i;
}

Но как насчет подписанных типов, меньших чем int, таких как short или signed char? (меньшим я предполагаю, что SCHAR_MAX < INT_MAX и SHRT_MAX < INT_MAX соответственно).

Какие из перечисленных ниже функций вызывают неопределенное поведение и почему?

signed char test2(void) {
    signed char i = SCHAR_MAX;
    i = i + 1;   /* implementation defined */
    return i;
}

signed char test3(void) {
    signed char i = SCHAR_MAX;
    i += 1;   /* undefined behavior or implementation defined? */
    return i;
}

signed char test4(void) {
    signed char i = SCHAR_MAX;
    i++;      /* undefined behavior or implementation defined? */
    return i;
}

signed char test5(void) {
    signed char i = SCHAR_MAX;
    ++i;      /* undefined behavior or implementation defined? */
    return i;
}

Пожалуйста, предоставьте ссылки или цитируйте стандарт C, чтобы поддержать ваши рассуждения.

7 голосов | спросил chqrlie 31 +03002016-10-31T17:01:44+03:00312016bEurope/MoscowMon, 31 Oct 2016 17:01:44 +0300 2016, 17:01:44

2 ответа


0

Было бы логично, чтобы += и аналогичные операторы работали непосредственно со значениями типа назначения и со многими реализациями, которые на самом деле, что они делают. Стандарт, однако, требует, чтобы оператор вел себя так, как если бы значение пункта назначения подвергалось любым применимым промоушенам стандарта и балансировки, затем обрабатывал указанную операцию и затем преобразовывался обратно в тип назначения.

Следовательно, если s и u являются 16-битными переменными со знаком и без знака, а int равно 32 битам, тогда s*=s; будет определено для всех значений s [если результат превышает 32767, он должен либо дать значение, определяемое реализацией, или повышать сигнал, определяемый реализацией; большинство реализаций должно было бы сделать все возможное, чтобы сделать что-то кроме сокращения двух дополнений]. С другой стороны, u*=u; будет гарантированно упаковывать мод 65536 только для значений u до 46340; для больших значений он вызовет неопределенное поведение.

ответил supercat 31 +03002016-10-31T17:47:06+03:00312016bEurope/MoscowMon, 31 Oct 2016 17:47:06 +0300 2016, 17:47:06
0

Следующий код вызывает и переполняет и, следовательно, не определяет поведение:

signed char i = SCHAR_MAX;
i++; 

Оператор postfix ++ не выполняет целочисленных повышений или обычных арифметических преобразований 1 . Оператор просто добавляет единицу к значению операнда 2 . Операции переполнены.

Четкое различие заключается в формулировке унарных арифметических операторов: +, -, ~, для которого в формулировке четко сказано, что операнд повышен 3 . Но для постфиксного оператора ++ в формулировке не говорится, что оператор повышен до 4 .

Очевидно, что оператор postfix ++ не продвигает операнд.


1 (цитируется по: ISO /IEC 9899: 201x 6.3.1.1 Boolean, символы и целые числа 2 58))
Целочисленные продвижения применяются только: как часть обычных арифметических преобразований, к определенным Выражения аргументов для операндов унарных операторов +, - и ~, а также для обоих операндов операторы сдвига, как указано в их соответствующих подпунктах.

2 (цитируется по: ISO /IEC 9899: 201x 6.5.2.4 Операторы увеличения и уменьшения постфикса 2)
Как побочный эффект, значение объекта-операнда увеличивается (то есть значение 1 соответствующего типа добавил к нему)

3 (цитируется по: ISO /IEC 9899: 201x 6.5.3.3 Унарные арифметические операторы 2)
Результатом унарного оператора + является значение его (повышенного) операнда. Целое число продвижение выполняется на операнде, и результат имеет продвинутый тип.

4 (цитируется по: ISO /IEC 9899: 201x 6.5.2.4 Операторы приращения и уменьшения постфикса 2)
Результатом оператора postfix ++ является значение операнда.

ответил 2501 31 +03002016-10-31T17:25:02+03:00312016bEurope/MoscowMon, 31 Oct 2016 17:25:02 +0300 2016, 17:25:02

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132