Эффект использования запятой вместо полуколонии в C и С++
Я неоднократно замечал, когда рефакторинг различных фрагментов кода на C и С++ используется вместо запятой, а не в виде двоеточия. Что-то вроде этого;
int a = 0, b = 0;
a = 5, b = 5;
Где бы я ожидал
int a = 0, b = 0;
a = 5; b = 5;
Я знаю, что C и С++ позволяют использовать запятые для разделения операторов (особенно заголовков контуров), но в чем разница между этими двумя фрагментами кода? Я предполагаю, что запятая была оставлена в результате вырезания и вставки, но является ли она ошибкой и выполняет ли она эффект?
Ответы
Ответ 1
Это не влияет на код, который вы опубликовали. В общем случае запятая разделяет выражения так же, как точку с запятой, однако, если вы принимаете целое как выражение, то оператор запятой означает, что выражение оценивается последним аргументом.
Вот пример:
b = (3,5);
Будет оценивать 3, затем 5 и назначить последнему b. Итак, b == 5. Обратите внимание: здесь важны скобки:
b = 3, 5;
Будет оценивать b = 3, затем 5, а результат всего выражения равен 5, тем не менее b == 3.
Оператор запятой особенно полезен для for-loops, когда ваш код итератора не является простым я ++, но вам нужно сделать несколько команд. В этом случае точка с запятой не работает с синтаксисом for-loop.
Ответ 2
Запятая - это оператор, который возвращает значение, которое всегда является 2-м (правым) аргументом, в то время как точка с запятой просто заканчивается. Это позволяет использовать оператор запятой внутри других операторов или конкатенировать несколько операторов как один.
Здесь функция f (x) вызывается, а затем x > y
вычисляется для оператора if.
if( y = f(x), x > y )
Пример, когда он использовался только для того, чтобы избежать необходимости в блоке
if( ... )
x = 2, y = 3;
if( ... ) {
x = 2;
y = 3;
}
Ответ 3
Оператор запятой оценивает все операнды слева направо, а результат - значение последнего операнда.
В большинстве случаев это полезно для for-loops, если вы хотите сделать несколько действий в части "increment", например (реверсив строку)
for (int lower = 0, upper = s.size() - 1; lower < upper; ++lower, --upper)
std::swap(s[lower], s[upper]);
Другой пример, где это может быть опция (поиск всех вхождений в строке):
#include <string>
#include <iostream>
int main()
{
std::string s("abracadabra");
size_t search_position = 0;
size_t position = 0;
while (position = s.find('a', search_position), position != std::string::npos) {
std::cout << position << '\n';
search_position = position + 1;
}
}
В частности, логические и не могут использоваться для этого условия, поскольку как нулевой, так и ненулевой могут означать, что символ был найден в строке. С другой стороны, с запятой position = s.find()
вызывается каждый раз, когда условие оценивается, но результат этой части условия просто игнорируется.
Естественно, существуют и другие способы записи цикла:
while ((position = s.find('a', search_position)) != std::string::npos)
или просто
while (true) {
position = s.find('a', search_position);
if (position == std::string::npos)
break;
...
}
Ответ 4
одно использование будет в игре с кодом:
if(x==1)y=2,z=3;
if(x==1){y=2;z=3;}
первая строка короче, но это выглядит слишком запутанным для использования в регулярной разработке
Ответ 5
Как Фрэнк упоминал, как используется оператор запятой в вашем примере, не вызывает ошибки. Оператор запятой может вводить в заблуждение по нескольким причинам:
- он не встречается слишком часто, потому что он необходим только в некоторых особых ситуациях.
- существует несколько других синтаксических применений запятой, которые могут выглядеть как оператор запятой, но они не являются (запятые, используемые для разделения параметров/аргументов функции, запятых, используемых для разделения объявлений переменных или инициализаторов)
Так как это запутывает и часто ненужно, следует избегать оператора запятой, за исключением некоторых очень специфических ситуаций:
- может быть полезно выполнить несколько операций в одном или нескольких операторах
for
, управляющих выражениями
- он может использоваться в макросах препроцессора для оценки более одного выражения в одном выражении. Обычно это делается для того, чтобы макросы могли делать больше, чем одно, и все еще быть одним выражением, поэтому макрос будет "соответствовать" в местах, которые позволяют только выражение.
Оператор запятой довольно хакерский оператор по определению - он должен взломать 2 вещи, где разрешено только одно. Это почти всегда уродливо, но иногда это все, что у тебя есть. И это единственный раз, когда вы должны его использовать - если у вас есть другой вариант, не используйте оператор запятой.
Сверху моей головы я не могу думать о слишком многих других причинах использования оператора, так как вы можете получить аналогичный эффект, оценивая выражения в отдельных утверждениях в большинстве других ситуаций (хотя я уверен, что кто-то прокомментирует другое использование, которое я упустил).