Эффект использования запятой вместо полуколонии в 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 вещи, где разрешено только одно. Это почти всегда уродливо, но иногда это все, что у тебя есть. И это единственный раз, когда вы должны его использовать - если у вас есть другой вариант, не используйте оператор запятой.

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