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

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

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

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

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

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

62
задан Glen 18 January 2010 в 15:32
поделиться

5 ответов

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

Вот пример:

b = (3, 5);

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

b = 3, 5;

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

Оператор запяты особенно полезен для циклов, когда ваш код итератора не является простым I ++ , но вам нужно делать несколько команд. В этом случае съемка не работает хорошо с синтаксисом для петли.

93
ответ дан 24 November 2019 в 16:43
поделиться

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

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

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

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

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

if( ... ) {
   x = 2;
   y = 3;
}
22
ответ дан 24 November 2019 в 16:43
поделиться

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

Это в основном полезно для петлей, если вы хотите делать несколько действий в разделе «Приращение», например, (изменение строки)

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

в частности, логично и нельзя использовать для этого условия, поскольку как нулевые, так и ненулевые, могут означать, что символ был найден в строке. С запятой, с другой стороны, положение = 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;
    ...
}
8
ответ дан 24 November 2019 в 16:43
поделиться

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

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

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

4
ответ дан 24 November 2019 в 16:43
поделиться

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

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

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

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

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

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

3
ответ дан 24 November 2019 в 16:43
поделиться