Эффект использования запятой вместо точки с запятой в C и c++



Я заметил в ряде случаев при рефакторинге различных частей кода C и C++, что для разделения операторов используется запятая, а не точка с запятой. Что-то вроде этого;



int a = 0, b = 0;
a = 5, b = 5;


где бы я ожидал



int a = 0, b = 0;
a = 5; b = 5;


Я знаю, что C и C++ позволяют использовать запятые для разделения операторов (особенно заголовков циклов), но в чем разница между этими двумя частями кода? Я предполагаю, что запятая была оставлена в результате разреза & вставка, но это ошибка и влияет ли она на выполнение?

568   5  
c

5 ответов:

это не имеет значения в коде, который вы опубликовали. В общем случае запятая разделяет выражения так же, как точка с запятой, однако, если вы берете целое как выражение, то оператор запятой означает, что выражение вычисляется до последнего аргумента.

вот пример:

b = (3, 5);

оценит 3, затем 5 и назначит последнее b. So b = 5. Обратите внимание, что скобки здесь важны:

b = 3, 5;

оценить b = 3, затем 5 и результат всего выражения равен 5, тем не менее b == 3.

оператор запятой особенно полезен в циклах for, когда ваш код итератора не является простым i++, но вам нужно сделать несколько команд. В этом случае точка с запятой не очень хорошо работает с синтаксисом for-loop.

запятая-это оператор, который возвращает значение, которое всегда является 2-м (правым) аргументом, а точка с запятой просто завершает операторы. Это позволяет оператору запятой использоваться внутри других операторов или объединять несколько операторов в один.

здесь вызывается функция f (x), а затем x > y вычисляется для оператора if.

if( y = f(x), x > y )

пример, когда он используется только для того, чтобы избежать необходимости в блоке

if( ... )
   x = 2, y = 3;

if( ... ) {
   x = 2;
   y = 3;
}

оператор "запятая" вычисляет операнды слева направо, и результатом является значение последнего операнда.

это в основном полезно в for-loops, если вы хотите сделать несколько действий в части "инкремент", например (реверсирование строки)

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;
    ...
}

одно использование будет в гольф код:

if (x == 1) y = 2, z = 3;
if (x == 1) { y = 2; z = 3; }

первая строка короче, но это выглядит слишком запутанным для использования в регулярной разработке.

Как Фрэнк упомянул, как оператор запятая используется в вашем примере не вызывает ошибку. Оператор запятой может сбивать с толку по нескольким причинам:

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

поскольку это сбивает с толку и часто не нужно, оператор запятой следует избегать, за исключением некоторых очень специфических ситуаций:

  • может быть полезно выполнить несколько операций в одном или нескольких из for управляющие выражения оператора
  • он может использоваться в макросах препроцессора для вычисления более одного выражения в одном операторе. Обычно это делается для того, чтобы макросы могли выполнять несколько действий и все же это одно выражение, поэтому макрос будет "вписываться" в места, которые позволяют только выражение.

оператор запятой является хакерским оператором в значительной степени по определению - это взломать 2 вещи, где разрешено только одно. Это почти всегда уродливо, но иногда это все, что у вас есть. И это единственный раз когда вы должны использовать его, если у вас есть другой вариант, не использовать оператор запятая.

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

Comments

    Ничего не найдено.