Re: в чем смысл -Wparentheses-equality ?
От: watchmaker  
Дата: 01.06.20 14:41
Оценка: 125 (16) +4
Здравствуйте, niXman, Вы писали:

X>столкнулся с сабжевым ворнингом и не понимаю, в чем смысл этого ворнинга?


K&R добавляли в свой язык разные прикольные фишки вроде while(*s++), которые выглядели красиво, хорошо ложились на тогдашнее железо, но которые в ретроспективе оказались весьма неоднозначным и иногда даже вредным наследием (например, https://queue.acm.org/detail.cfm?id=2010365 ).

Одна из таких фишек: что оператор присваивания = можно использовать внутри выражений. Само по себе это не плохо, но вкупе с его пожестью на оператрор равенства == это легко приводит к тому, что опечатка в условии остаётся незамеченной, так как программа остаётся корректной программой на C:
if (a == b) { ... }
// vs.
if (a = b) { ... }


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

Но такая конструкция, например, вполне корректно используется при обходе связанного списка: while(list = list->next) ... . Почему бы не записать отдельно присваивание и отдельно проверку в две строки? Ну по той же причине, по которой K&R оставили while(*s++) — так короче, прикольнее, красивее и (со временем) даже идиоматичнее.

Но что-то с этим надо было делать и компиляторостроители решили, что warning можно не выдавать, если подобные конструкции записаны так
while((list = list->next) != NULL) ...

или так
while((list = list->next)) ...


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


Но теперь возможна и обратная ситуация, когда вместо оператора присваивания = написан оператор сравнения ==.
На примере того же обхода списка
while((list == list->next) != NULL) ... // компилируется, но содержит ошибку

while((list == list->next)) ... // компилируется, но содержит ошибку



И тут появляется предупреждение parentheses-equality — оно в некотором роде обратное и призвано ловить код, в котором с высокой вероятностью хотели написать присваивание, но написали сравнение.
Но само по себе это недостаточно сильное основание для включения parentheses-equality в компилятор — проверка полезная, но с риском ложных срабатываний, которые тоже вредят отвлекая внимание (сотни таких "условно-полезных" проверок можно выдумать для C/C++)

Жгёт это предупреждение из-за работы в паре с другими проверками на использование операторов сравнения/равенства и скобок:
int a, b;
...
if (a == b) ...

if ((a = b)) ...

Обе эти конструкции компилируются без предупреждений и ошибок.
Но теперь запись if (a = b) выведет предупреждение и запись if ((a == b)) выведет предупреждение.
То есть сила -Wparentheses-equality в том, что теперь недостаточно опечататься в одном символе, чтобы молча привести одну конструкцию к другой — теперь нужно изменить минимум три символа в коде (один = и пару скобок). И программа стала в целых три раза устойчивее к опечаткам!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.