Вопрос

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

Это было полезно?

Решение

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 Page 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 более понятнее, но это верно на обоих языках.

Другие советы

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

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

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


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

Компилятор может поразить параметры в обратном порядке, передний порядок или что-то еще. Это может вызвать первый вывод, прежде чем вычисление параметра на второй выход или может сделать оба, а затем вызов.

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

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

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

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

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

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

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

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

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

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

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

Это не устраняет требование для точек последовательности.

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

Как я вижу это, f (C ++); эквивалентно: f (c); C + = 1;

И f (C ++, C ++); эквивалентно: f (c, c); C + = 1; C + = 1;

Но это может быть так, что f (C ++, C ++); становится f (C, C + 1); C + = 2;

Эксперимент с GCC и Clang, первый в C

#include <stdio.h>

void f(int a, int b) {
    printf("%d %d\n",a,b);
}

int main(int argc, char **argv) {
    int c = 0;
    f(c++,c++);

    return 0;
}

А в C ++

#include <iostream>

int main(int argc, char **argv) {
    int c = 0;
    std::cout << c++ << " " << c++ << std::endl;
    return 0;
}

Интересно, как GCC и G ++ скомпилированы результаты в 1 0, тогда как Clang Compiced результаты в 0 1

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top