Разделители запятой в определении типа в C гарантируют заказ?
Comma операторы имеют младший приоритет и ассоциативность слева направо, поэтому это гарантирует порядок:
i = ++j, j = i++;
i
будет равно 2, а затем j
будет 1 после этого утверждения, если i
и j
будут одновременно 0.
Однако, действительно ли запятые разделители в определении типа в C также гарантируют порядок? Например,
int i = 1, j = ++i;
Ответы
Ответ 1
Ваш пример с оператором запятой i = ++j, j = i++;
, является корректным, поскольку оператор запятой является точкой последовательности.
Приоритет/ассоциативность недостаточно для того, чтобы гарантировать это - они отличаются от порядка оценки и точек последовательности. Например, i * 2 + i++ * 3
- undefined, потому что нет точек последовательности.
Разделитель запятой между деклараторами, например. int i = 1, j = i++;
, также является точкой последовательности. Это охватывается C11 6.7.6/3, C99 6.7.5/3:
Полный декларатор - это декларатор, который не является частью другого декларатора. Конец полного декларатора является точкой последовательности.
Итак, после i = 1
есть точка последовательности, и этот код определен корректно.
Однако разделитель запятой между аргументами функции f(i, i++)
не является точкой последовательности; так что код вызывает поведение undefined.
Примечание. В C11 термин "точка последовательности" в основном заменялся более сложными отношениями секвенирования, чтобы четко указать модель потоковой передачи, но это не влияет на описанное выше обсуждение.
Ответ 2
Да, и вот причина. Подумайте, что говорит запятая. Все, что он говорит, это "эй, у меня есть вещь, которую я хочу сделать в левой части этой запятой, как только вы это сделаете, идите к делу справа и сделайте это. Вы также можете думать об этом как о более короткий способ сделать это
int i = 1;
int j = i++;
i уже был выделен где-то в памяти, поэтому все, что происходит с j, - это значение, которое хранится в i, увеличивает его и устанавливает его равным j.
Итак, в случае
int i = 1, j = ++i;
Все, что вы говорите, - это создать целое число, установить его равным единице, теперь перейти к следующей команде, которая будет int с именем j, и установить ее равной тому, что я есть, когда она увеличивается.
Итак, чтобы полностью ответить на ваш вопрос, да, он гарантирует заказ, потому что компилятор выполнит все сверху вниз, слева направо, если не будет сказано иначе.
Ответ 3
Предполагая, что C работает так же, как С# в этом отношении, значения, разделенные запятыми (int я = 0, j = 0;), должны оставаться в порядке.
Разница в я ++ vs ++ я - время проверки:
int i = 0;
bool iGTZ = i++ > 0;//false
i = 0; iGTZ = ++i > 0;//true
Немного больше, чем вы просили, но заказ объявления гарантирован. И если вы или кто-то читающий это не знали, что, надеюсь, это помогает.:)