Ответ 1
Стандарт ясно описывает порядок оценки операндов оператора сдвига.
n4659 - §8.8 (p4):
Выражение
E1
секвенируется перед выражениемE2
.
В выражении i++ << i
нет неопределенного поведения, оно четко определено. Это ошибка в Clang и GCC.
Я читал в С++ 17 Standard $ 8.5.7.4:
Выражение E1 секвенируется перед выражением E2.
для операторов сдвига.
Также правило 19 правила cppreference говорит:
In a shift operator expression E1<<E2 and E1>>E2, every value
computation and side-effect of E1 is sequenced before every value
computation and side effect of E2
Но когда я пытаюсь скомпилировать следующий код с gcc 7.3.0 или clang 6.0.0
#include <iostream>
using namespace std;
int main() {
int i = 5;
cout << (i++ << i) << endl;
return 0;
}
Я получаю следующее предупреждение gcc:
../src/Cpp_shift.cpp: In function ‘int main():
../src/Cpp_shift.cpp:6:12: warning: operation on ‘i may be undefined [-Wsequence-point]
cout << (i++ << i) << endl;
~^~
Предупреждение о кланге:
warning: unsequenced modification and access to 'i' [-Wunsequenced]
Я использовал следующие команды для компиляции:
g++ -std=c++17 ../src/Cpp_shift.cpp -o Cpp_shift -Wall
clang++ -std=c++17 ../src/Cpp_shift.cpp -o Cpp_shift -Wall
Я получаю ожидаемый результат 320
в обоих случаях (5 * 2 ^ 6)
Может кто-нибудь объяснить, почему я получаю это предупреждение? Я что-то пропустил? Я также прочитал этот связанный вопрос, но он не отвечает на мой вопрос.
edit: все остальные варианты ++i << i
, i << ++i
и i << i++
приводят к i << i++
же предупреждению.
edit2: (i << ++i)
приводит к 320
для clang (правильно) и 384
для gcc (неверно). Кажется, что gcc дает неправильный результат, если ++
находится в E2
, (i << i++)
также дает неправильный результат.
Стандарт ясно описывает порядок оценки операндов оператора сдвига.
n4659 - §8.8 (p4):
Выражение
E1
секвенируется перед выражениемE2
.
В выражении i++ << i
нет неопределенного поведения, оно четко определено. Это ошибка в Clang и GCC.