Является ли func() + func() неопределенным поведением?

Я только знаю i = i++; является неопределенным поведением, но если в выражении вызываются две или более функций, и все функции одинаковы. Это неопределенно? Например:

int func(int a)
{
    std::cout << a << std::endl;
    return 0;
}

int main()
{
    std::cout << func(0) + func(1) << std::endl;
    return 0;
}

3 ответа

Решение

Поведение выражения func(0) + func(1) определяется тем, что результатом будет сумма результатов, полученных путем вызова func с параметром 0 а также funcс параметром 1,

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

int a = func(0);
int b = func(1);
int result = a + b;

Или это может сгенерировать:

int a = func(1);
int b = func(0);
int result = a + b;

Это обычно не будет проблемой, если func имеет побочные эффекты, которые зависят от порядка звонков.

Поведение этой программы не является неопределенным, но оно не определено, если мы посмотрим на черновик стандартного раздела C++ 1.9 Пункт 15 выполнения программы гласит (выделение мое):

За исключением отмеченных случаев, оценки операндов отдельных операторов и подвыражений отдельных выражений не являются последовательными. [Примечание: В выражении, которое оценивается более одного раза во время выполнения программы, непоследовательные и неопределенно последовательные оценки ее подвыражений не должны выполняться последовательно в различных оценках. - примечание конца] Вычисления значений операндов оператора секвенируются до вычисления значения результата оператора. Если побочный эффект на скалярный объект не секвенирован относительно другого побочного эффекта на тот же скалярный объект или вычисления значения с использованием значения того же скалярного объекта, поведение не определено.

и если мы проверим раздел 5.7 Аддитивные операторы, которые охватывают + а также - этот раздел не определяет порядок, поэтому он не упорядочен.

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

Обратите внимание, что ; заканчивает выражение выражения и раздел 6.2 Выражение высказывания гласит:

[...] Все побочные эффекты от выражения выражения завершаются до выполнения следующего оператора.[...]

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

std::cout << func(0) + func(1) << std::endl;

Будь функция вызова func(0) или же func(1) выполняется первым, зависит от реализации. После этого есть точка последовательности, и func(0) + func(1) это выход.

Но по определению это не называется неопределенным поведением.

Другие вопросы по тегам