Ознакомьтесь с нашей политикой обработки персональных данных
23:48 

Операция запятая в Си: "Операция "Факап"

zHz00
Описано, как не надо применять операцию "запятая" в Си.

Придётся смириться: в языке Си есть запятая. Запятая есть двух видов -- разделительная и "операция запятая".

Разделительная запятая применяется:
1. При перечислении в об'явлении переменных: int a, b, c;
2. При перечислении параметров фукнции (макросов это тоже касается): int f(int a, int b, int c); -- и потом f(7,3,2).
3. При инициализации массивов и структур: int a[3]={1,2,3};
В Си++ есть ещё несколько случаев, но на них я останавливаться не буду.

Все остальные запятые -- это "операции запятые"!

Когда студенты спрашивают, почему я про неё рассказываю, когда от неё так мало пользы, я отвечаю, что по двум причинам:
1. Чтобы вы смогли её опознать в чужом тексте, если какой-нибудь умник её применит.
2. Чтобы сами не писали её там, где её быть не нужно, ожидая иного поведения (об этом, собственно, данная статья).

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

Пример 1.
a=2,b=3;
В a 2, в b 3, результат -- 3.

Пример 2.
2,3;
Результат -- 3.

Пример 3.
a=3,b=a+3,7;
В a 3, в b 6, результат -- 7.

Пример 4.
a=3+5,3+7;
Вот тут очень важный момент. У "запятой" минимальный приоритет, поэтому сначала выполняется присваивание и в a 8, но результат операции 10. Я всё говорю про результат, но как его получить-то, когда даже присваивание выполняется раньше? Искусственно поменять приоритет.

Пример 5.
a=(3+5,3+7);
В a -- 10, результат выражения -- 10.

Можно долго распинаться о пользе этой операции, но за меня это уже сделали. Пожалуйста: iproc.ru/programming/cpp-comma-operator/ .

Я остановлюсь на факапах, которые происходят по её вине. Чаще всего это бывает у очень сильно начинающих писать на Си (Си++, PHP, Java, Javasсript -- вас всех это тоже касается!). Часто вижу на примере студентов.

Начнём с безобидного.

Факап 1. for(x=0,x<100,x++)
Не знаю, что заставляет писать так. Видимо, пишется по памяти. Но после написания 2-3 рабочих циклов такого уже не должно происходить. Почему безобидное, потому что не будет компилироваться.

Факап 2. return a,b;
Хочется вернуть два значения сразу! Но нельзя. Вернётся b. Когда это увидел ssvda, он сказал, что автору данной строки нужно учить Python, там такое работает.
Я, правда, применяю подобную конструкцию в виде return printf("Error opening file\n"),ERROR_FILE_OPEN;
В одну строчку выводит сообщение об ошибке и возвращает её код. За такое надо убивать (меня).

Факап 3. int volume, r=3; volume=4/3*3,14*r^3;
Эти не знают, что в Си -- десятичная точка, а не запятая. И ещё не знают, что крышка -- это поразрядное исключающее "или". В volume будет 3. Про об'ём как целое число -- ладно, фиг с ним.

Факап 4. int a[3][3]; a[1,2]=0;
Для тех, кто раньше писал на Паскале/Делфи, МАТЛАБе и чёрт знает чём ещё может быть совершенно неочевидно, что в данном случае тоже! применяется операция запятая. a[1,2] эквивалентно a[2]. Но a[2] имеет тип const int *. Не скомпилируется. Но если многомерный массив -- динамический, то даже предупреждения не будет.

Факап 5. while(a>3, c>2)
Имелось ввиду while(a>3&&c>2). В данном случае будет проверяться лишь второе условие.

Факап 6. Приплюснутое. delete t1,t2;
delete -- такая же операция, как и остальные и тоже имеет свой ранг в таблице приоритетов. Поэтому сначала будет вычислено delete t1 (указатель удалён, результат: void), потом t2 (результат: t2), а результатом будет последнее выражение (t2). t2 удалён не будет! (спасибо за поддержку: himself)

Факап 7. Приплюснутое, часть 2. throw 1, 2;
См. факап 6. То же.

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

@темы: Программирование, Статьи

URL
Комментарии
2014-12-12 в 00:01 

Да вы просто гуру!

URL
2014-12-12 в 00:03 

zHz00
Гость, да вы издеваетесь. Но про операцию "запятая" знают не все, да.

URL
2014-12-12 в 02:37 

да вы издеваетесь

Я не программист, да ещё и гуманитарий. Для меня человек, который понимает что-то в этих заклинаниях - гуру (если не считать, что однажды я сам для себя написал мод к Hearts of Iron III (но там было руководство по написанию модов)).

URL
2015-01-17 в 13:27 

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

-- Minoru

URL
   

Untitled

главная