2016-11-10 1 views
7

ПРИМЕР Пример неопределенного поведения - это поведение при переполнении целых чисел. C11dr §3.4.3 3Когда значение `int` at max и проверено с помощью postfix ++, является ли код корректным?

int переполнение не определено поведение, но это применимо к следующему, который существует цикл, и не использует побочный эффект теперь вне сферы i? В частности, делает ли это Postfix increment spec help?

... Вычисление значения результата секвенируется перед побочным эффектом , обновляющим сохраненное значение операнда. ... §6.5.2.4 2

компилировать без предупреждения с хорошо включен C11

#include <limits.h> 
#include <stdio.h> 

int main(void) { 
    // Specified behavior when `i` has the value `INT_MAX`? 
    for (int i = INT_MAX - 2; i++ < INT_MAX;) { 
    printf("%d\n", i); 
    } 
    puts("Done"); 
    return 0; 
} 

Пример вывода

2147483646 
2147483647 
Done 

Конечно код может быть переписан, чтобы избежать этого затруднительного положения с ниже. Тем не менее, ища подтверждения относительно вышеизложенного. (Я думаю, что это UB.) Аналогичная проблема существует с INT_MIN и i--.

for (int i = INT_MAX - 2; i < INT_MAX;) { 
    i++; 
    printf("%d\n", i); 
    } 

GNU C11 (GCC) version 5.3.0 (i686-pc-cygwin) 
    compiled by GNU C version 5.3.0, GMP version 6.1.0, MPFR version 3.1.4, MPC version 1.0.3 
'-std=c11' '-O0' '-g3' '-Wpedantic' '-Wall' '-Wextra' '-Wconversion' '-c' '-fmessage-length=0' '-v' '-MMD' '-MP' '-MF' xx.o' '-o' 'xx.o' '-mtune=generic' '-march=i686' 
/usr/lib/gcc/i686-pc-cygwin/5.3.0/cc1.exe -quiet -v -MMD xx.d -MF xx.d -MP -MT xx.o -dD -Dunix -idirafter ... xx.c 
+1

Я мог бы смутить, но я не думаю, что 'i' когда-либо переполняется в любом случае, не останавливается, когда он равен INT_MAX – Vality

+0

@Vality Да, execuatble остановился, когда' i ++ 'возвратил' INT_MAX', как показано в выход образца. Вопрос в том, хорошо ли это поведение. – chux

ответ

4

Независимо от объема i, программа имеет неопределенное поведение в evaluaton из i++ когда i является 2147483647 (при условии, INT_MAX = 2147483647 на вашей системе).

Ваш пример может быть повторно записан в виде:

include <limits.h> 

int main(void) { 
    // Specified behavior when `i` has the value `INT_MAX`? 
    { 
     int i = INT_MAX; 
     i++; 
    } 
    puts("Done"); 
    return 0; 
} 

Значение вычисление i++ результатов в целочисленном переполнении, независимо от того, используется ли вычисленное значение, или если этот объект перестает существовать сразу после следующей точки последовательности ; точка последовательности или длительность хранения объекта не имеет значения, существует ли неопределенное поведение здесь.

+0

Хороший вопрос. Более близким кодом может быть 'while (1) {int i = INT_MAX; if (i ++ == INT_MAX) break; } ', поскольку я пытаюсь понять, как, по возможности,' i ++ 'является разделимым. Результат секвентируется до инкремента на спецификацию. Я думаю, вопрос может быть, если 'if (_test_the return_value_)' является выходом из ожидающего '++' UB - видимо, нет. – chux

4

код имеет неопределенное поведение. Выражение i++ вызывает оценку i+1 и присвоение результата i, а оценка i+1 имеет неопределенное поведение. Не имеет значения, что вы не используете результат i+1 или недавно сохраненное значение i. UB - это не вопрос использования результата. Аналогично, 0*(INT_MAX+1) имеет UB.

+0

Согласитесь, что '0 * (INT_MAX + 1)' является UB, но в этом примере нет проблем с секвенированием/областью. Здесь 'i ++' имеет _side-effect_ и секвенируется после результата. Это тот атрибут, о котором мне интересно. – chux

+0

Я не понимаю, как вы думаете, что последовательность UB имеет отношение к UB. Текст, который вы цитируете о последовательности, имеет значение в случаях, когда определяется результат; он не имеет смысла в случаях, когда программа имеет неопределенное поведение. –

+0

'i chux

Смежные вопросы