Как работает оператор запятая
-
09-06-2019 - |
Вопрос
Как работает оператор запятая в C++?
Например, если я это сделаю:
a = b, c;
Будет ли a в конечном итоге равным b или c?
(Да, я знаю, что это легко проверить — просто задокументируйте здесь, чтобы кто-то мог быстро найти ответ.)
Обновлять: Этот вопрос выявил нюанс при использовании оператора запятой.Просто чтобы задокументировать это:
a = b, c; // a is set to the value of b!
a = (b, c); // a is set to the value of c!
На самом деле этот вопрос был вызван опечаткой в коде.Что должно было быть
a = b;
c = d;
Превратился в
a = b, // <- Note comma typo!
c = d;
Решение
Это было бы равно b
.
Оператор запятая имеет более низкий приоритет, чем оператор присваивания.
Другие советы
Обратите внимание, что оператор запятая может быть перегружен в C++.Таким образом, фактическое поведение может сильно отличаться от ожидаемого.
В качестве примера, Повышение.Дух весьма умело использует оператор запятой для реализации инициализаторов списков для таблиц символов.Таким образом, это делает возможным и осмысленным следующий синтаксис:
keywords = "and", "or", "not", "xor";
Обратите внимание, что из-за приоритета операторов код (намеренно!) идентичен коду
(((keywords = "and"), "or"), "not"), "xor";
То есть первый вызванный оператор keywords.operator =("and")
который возвращает прокси-объект, на котором оставшиеся operator,
s вызываются:
keywords.operator =("and").operator ,("or").operator ,("not").operator ,("xor");
Оператор запятая имеет самый низкий приоритет всех операторов C/C++.Поэтому он всегда последним привязывается к выражению, что означает следующее:
a = b, c;
эквивалентно:
(a = b), c;
Еще один интересный факт заключается в том, что оператор запятая вводит точка последовательности.Это означает, что выражение:
a+b, c(), d
гарантированно будет иметь три подвыражения (а+б, с() и д) оцениваются по порядку.Это важно, если у них есть побочные эффекты.Обычно компиляторам разрешается вычислять подвыражения в любом порядке, который они считают подходящим;например, при вызове функции:
someFunc(arg1, arg2, arg3)
аргументы могут оцениваться в произвольном порядке.Обратите внимание, что запятые в вызове функции нет операторы;они являются сепараторами.
Оператор запятая:
- имеет самый низкий приоритет
- является левоассоциативным
Версия оператора запятой по умолчанию определена для всех типов (встроенных и пользовательских) и работает следующим образом: exprA , exprB
:
exprA
оценивается- результат
exprA
игнорируется exprB
оценивается- результат
exprB
возвращается как результат всего выражения
Для большинства операторов компилятору разрешено выбирать порядок выполнения и даже необходимо вообще пропустить выполнение, если это не влияет на конечный результат (например, false && foo()
пропустит звонок на foo
).Однако это не относится к оператору запятой, и описанные выше шаги всегда будут выполняться.*.
На практике оператор запятая по умолчанию работает почти так же, как точка с запятой.Разница в том, что два выражения, разделенные точкой с запятой, образуют два отдельных оператора, а разделение запятыми сохраняет все как одно выражение.Вот почему оператор запятая иногда используется в следующих сценариях:
- Синтаксис C требует одного выражение, не утверждение.напримерв
if( HERE )
- Синтаксис C требует одного оператора, не более, например.при инициализации
for
петляfor ( HERE ; ; )
- Если вы хотите пропустить фигурные скобки и сохранить один оператор:
if (foo) HERE ;
(пожалуйста, не делайте этого, это действительно некрасиво!)
Если утверждение не является выражением, точку с запятой нельзя заменить запятой.Например, запрещены:
(foo, if (foo) bar)
(if
это не выражение)- int x, int y (объявление переменной не является выражением)
В вашем случае у нас есть:
a=b, c;
, эквивалентныйa=b; c;
, при условии, чтоa
имеет тип, который не перегружает оператор запятой.a = b, c = d;
эквивалентноa=b; c=d;
, при условии, чтоa
имеет тип, который не перегружает оператор запятой.
Обратите внимание, что не каждая запятая на самом деле является оператором-запятой.Некоторые запятые, имеющие совершенно другое значение:
int a, b;
--- список объявлений переменных разделен запятыми, но это не операторы-запятыеint a=5, b=3;
--- это также список объявлений переменных, разделенных запятымиfoo(x,y)
--- список аргументов, разделенных запятыми.Фактически,x
иy
можно оценить в любой заказ!FOO(x,y)
--- список аргументов макроса, разделенных запятымиfoo<a,b>
--- список аргументов шаблона, разделенных запятымиint foo(int a, int b)
--- список параметров, разделенных запятымиFoo::Foo() : a(5), b(3) {}
--- список инициализаторов, разделенных запятыми, в конструкторе класса
* Это не совсем так, если применить оптимизацию.Если компилятор признает, что определенный фрагмент кода абсолютно не влияет на остальной код, он удалит ненужные операторы.
Дальнейшее чтение: http://en.wikipedia.org/wiki/Comma_operator
Значение a
будет b
, но значение выражение будет c
.То есть в
d = (a = b, c);
а будет равно b
, и d
было бы равно c
.
Значение b будет присвоено a.С c ничего не случится
Значение a будет равно b, поскольку оператор запятой имеет более низкий приоритет, чем оператор присваивания.
Да. Оператор запятой имеет более низкий приоритет, чем оператор присваивания.
#include<stdio.h>
int main()
{
int i;
i = (1,2,3);
printf("i:%d\n",i);
return 0;
}
Выход :я = 3
Потому что оператор запятая всегда возвращает крайнее правое значение.
В случае оператора запятой с оператором присваивания:
int main()
{
int i;
i = 1,2,3;
printf("i:%d\n",i);
return 0;
}
Выход:я = 1
Как мы знаем, оператор запятой имеет более низкий приоритет, чем оператор присваивания.....
Перво-наперво: Запятая на самом деле не является оператором, для компилятора это просто токен, который приобретает смысл. в контексте с другими токенами.
Что это значит и зачем беспокоиться?
Пример 1:
Чтобы понять разницу между значением одного и того же токена в другом контексте, мы рассмотрим этот пример:
class Example {
Foo<int, char*> ContentA;
}
Обычно новичок в C++ думает, что это выражение может/будет сравнивать вещи, но это абсолютно неверно. <
, >
и ,
токены зависят от контекста использования.
Правильная интерпретация приведенного выше примера, конечно же, заключается в том, что это создание шаблона.
Пример 2:
Когда мы обычно пишем цикл for с более чем одной переменной инициализации и/или более чем одним выражением, которые должны выполняться после каждой итерации цикла, мы также используем запятую:
for(a=5,b=0;a<42;a++,b--)
...
Значение запятой зависит от контекста употребления, здесь это контекст употребления. for
строительство.
Что на самом деле означает запятая в контексте?
Чтобы еще больше усложнить ситуацию (как всегда в C++), оператор запятой может быть перегружен (благодаря Конрад Рудольф за указание на это).
Возвращаясь к вопросу, Кодекс
a = b, c;
означает для компилятора что-то вроде
(a = b), c;
поскольку приоритет принадлежащий =
токен/оператор выше приоритета ,
жетон.
и это интерпретируется в контексте вроде
a = b;
c;
(обратите внимание, что интерпретация зависит от контекста, здесь это не вызов функции/метода или создание шаблона.)