Результат интервала c=0; суд <<C++ <<c;

Я думаю, что это должно быть 01, но кто-то говорит что ее "неопределенное", какая-либо причина этого?

5
задан Eyoka 8 April 2010 в 20:42
поделиться

4 ответа

c ++ одновременно является приращением и присвоением. Когда происходит присвоение (до или после другого кода в этой строке), остается на усмотрение компилятора. Это может произойти после cout << или раньше.

Это можно найти в стандарте C99 http://www.open-std.org/JTC1/SC22/wg14/www/docs/n1124.pdf

Вы можете найти это на странице 28 в pdf или в разделе 5.1.2.3

фактическое приращение p может происходить в любое время между предыдущей точкой последовательности и следующей точкой последовательности

Поскольку кто-то попросил стандарт C ++ (поскольку это Вопрос C ++) его можно найти в разделе 1.9.15 стр. 10 (или 24 в формате pdf)

оценки операндов отдельных операторов и подвыражений отдельных выражений неупорядочены

Он также включает следующий блок кода:

i = v[i++]; // the behavior is undefined
i = 7, i++, i++; // i becomes 9
i = i++ + 1; // the behavior is undefined

Я считаю, что объяснение стандарта C99 более ясное, но оно верно для обоих языков.

8
ответ дан 18 December 2019 в 13:12
поделиться

Причина, по которой он не определен, заключается в том, что компилятор может вычислять параметры функции в любом порядке.Подумайте, где вы вызываете функцию (потому что это так, но это легче представить, когда она используется в синтаксисе функции):


  cout.output(c++).output(c);

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

1
ответ дан 18 December 2019 в 13:12
поделиться

Это неопределенное поведение, если вы изменяете значение, а затем читаете его (или пытаетесь изменить его снова) без промежуточной точки последовательности. Концепция точки последовательности в C ++ является немного технической (вы можете немного прочитать об этом здесь ), но суть в том, что вставка потока ( << ) - это ] не точка последовательности.

Причина, по которой это поведение undefined, заключается в том, что в отсутствие точки последовательности компилятору разрешено изменять порядок операций любым способом, который он считает нужным. То есть разрешено получить значение c (и удерживать его для второй вставки), а затем выполнить послесловие c ++ , чтобы получить значение для первой вставки. Таким образом, вы не можете быть уверены, произойдет ли приращение до или после определения значения c для второй вставки.

4
ответ дан 18 December 2019 в 13:12
поделиться

Поведение определено, но не указано. Относительный порядок оценки двух использований буквы «c» в выражении не указан. Однако, если вы преобразуете его в функциональную нотацию, это будет выглядеть так:

cout.operator<<(c++).operator<<(c);

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

Если бы у вас не было перегруженного оператора:

int c=0;
int a = c++ << c;

Тогда поведение было бы неопределенным, потому что и изменение, и использование значения c без промежуточной точки последовательности.

Правка: последовательность litb , которую выводит на экран, просто неверна. Стандарт определяет (§1.9 / 17): «При вызове функции (независимо от того, является ли функция встроенной), существует точка последовательности после оценки всех аргументов функции (если есть), которая имеет место перед выполнением любых выражений или операторы в теле функции."

Это ясно написано с идеей, что аргументы оцениваются, затем (сразу после этого) выполняется тело функции. Последовательность, которую он предлагает, в которой оцениваются аргументы одной функции, затем аргументы другой, затем выполнение оба тела функции, похоже, не были предназначены, но также не запрещены. Это, однако, ничего не меняет - требование все еще таково: «... существует точка последовательности после оценки всех аргументов функции ( если есть) ... "

Последующий язык выполнения тела НЕ удаляет требование точки последовательности после оценки всех аргументов функции. Все другие оценки, будь то тела функции или другие аргументы функции следуют за этой точкой последовательности. Я могу быть таким же педантичным и извращенным, как и любой другой, относительно неправильного чтения того, что явно предназначено (но не , вполне заявлено) - но я не могу представить, как «существует точка последовательности после оценки всех аргументов функций ts "можно прочитать как означающее" НЕ существует точки последовательности после оценки всех аргументов функции. "

Точка зрения Нила, конечно же, верна: синтаксис, который я использовал выше, предназначен для функций-членов. Для перегрузки, не являющейся членом, синтаксис будет больше похож на:

operator<<(operator<<(cout,c++), c);

Однако это не отменяет требования для точек последовательности.

Насколько он не указан: на самом деле это довольно просто: после оценки всех аргументов функции есть точка последовательности, поэтому все аргументы для одного вызова функции должны быть полностью оценены (включая все побочные эффекты), затем аргументы для другой функции вызов может быть оценен (с учетом любых побочных эффектов от другого) - НО нет никаких требований о том, что аргументы вызова функции WHICH должны оцениваться первым или вторым, поэтому это может быть c , затем c ++ , или это может быть c ++ , затем c - но это должно быть одно или другое, а не чередование.

1
ответ дан 18 December 2019 в 13:12
поделиться
Другие вопросы по тегам:

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