LINUX.ORG.RU

Ваше отношение к конструкциям вида if (a=f) в Си и C++

 ,


0

2

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

Тех, кто не пишет на этих языках, прошу выбирать соответствующий пункт и в остальной части опроса не участвовать.

Существует, в целом, три варианта отношения к конструкциям вида if (a=f). Первый — конструкция полностью нормальная, нет причин на неё гнать. Второй — опасения спутать = и == и на этом основании объявление данной конструкции вредной. Третий (почему-то про него вспоминают реже чем про первые два) — заявления о том, что не-булевы выражения (речь тут не конкретно про присваивание) в качестве условия if вообще так или иначе не совсем нормальная ситуация.

Часто сторонники второго варианта начинают потом писать про опечатки «которые у всех бывают», но я считаю нужным данную ситуацию прояснить: следует чётко отличать спутывание = и == по причине забывания как в Си пишется сравнение (в этом случае проблемой будет только =/== и ни что другое, и происходит такое, в первую очередь, у сильно неопытных программистов), и опечатки по причине, условно, нажимания не тех кнопок на клавиатуре — такое действительно случается у всех, но в этом случае конкретно присваивание никакой особенной роли не играет, речь идёт вообще о разных «способах» написать в скобках после if что-то неправильное и не заметить это. При этом, поскольку if по смыслу означает проверку условия, логично ожидать в скобках что-то булевое, а все остальные варианты объявить симптомами опечаток, подлежащими как минимум пристальному рассмотрению.

Те, кто так или иначе считает такую конструкцию проблемной (и включают соответствующий варнинг компилятора), дальше делятся ещё на два варианта: одни призывают вообще её избегать в любом виде, вторые же допускают её применение, но с явной подсказкой компилятору/программисту в виде дополнительных круглых скобок вокруг: if((a=f)).

И ещё один момент: даже те, кто не усматривает в данной конструкции опасность, иногда всё равно её избегают, по эстетическим/стилевым причинам (для удобства чтения итд). Это, как и всё вышенаписанное, учтено в опросе.

Для участия в опросе войдите или зарегистрируйтесь.

>>> Результаты

★★★★★

Проверено: hobbit ()
Последнее исправление: hobbit (всего исправлений: 11)

Бывает специально использую, бывает специально не использую. Конвенции допустимости, того или иного, я принимаю самостоятельно, в зависимости от того что делаю. Аналогичная фигня с goto где-то с радостью пропишу, получив элегантное решение, а где-то открещиваться буду. Если теоретические проблемы не перевешивают явную выгоду и удобство, то почему нет. Если теоретическая выгода не факт что перевесит гарантированные проблемы, то ну его нахер =)

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

LINUX-ORG-RU ★★★★★
()
Последнее исправление: LINUX-ORG-RU (всего исправлений: 1)

у всех бывают опечатки, и дело не в =/== а вообще в автоконверсии int->bool, конструкцию осуждаю и включаю варнинг

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

Дело вовсе не в том, что у всех бывают опечатки, а в том, что такой код тяжелее читается. Ну очень уж легко не обратить внимание при беглом просмотре (да и даже не беглом, особенно если уставший или ищешь баг, причины которого слабо понятны), что там не ==, а =. Мозг автоматически «видит» более привычные шаблоны — примерно так же, как легко не замтеить опечатку в длинном слове в обычном тексте. Если есть двойные скобки, или комментарий, бросающийся в глаза и говорящий, мол, обрати внимание, здесь не сравнение, это исправляет ситуацию, и тогда отношусь нормально.

CrX ★★★★★
()

Эту конструкцию полагается оборачивать в дополнительные скобки, даже специальный ворнинг для этого придумали
Если я сам пользуюсь этой конструкцией и считаю её нормальной, но только со скобками - мне какой вариант выбирать?

mittorn ★★★★★
()
Последнее исправление: mittorn (всего исправлений: 1)
Ответ на: комментарий от mittorn

Предпоследний же - там как раз ровно то что ты написал указано.

Наверно и правда немного не очевидно, чуть поправлю формулировки.

И добавил ещё один пункт, так что теперь у тебя выбор из пред-пред-последнего и предпоследнего.

firkax ★★★★★
() автор топика
Последнее исправление: firkax (всего исправлений: 3)
Ответ на: комментарий от CrX

Следующий за этим вариант же «оборачиваю в двойные скобки». Конечно это означает, что без двойных скобок тебе она не нравится.

Дело вовсе не в том, что у всех бывают опечатки, а в том, что такой код тяжелее читается

А, это и правда какой-то другой вариант. Добавлю сейчас.

firkax ★★★★★
() автор топика

другой вариант (напишу в комментариях)

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

Sm0ke85
()
Последнее исправление: Sm0ke85 (всего исправлений: 1)

Технически корректно, но 9 случаев из 10 это описка. Некоторые статические анализаторы и линтеры будут крошить батон на такую строку - имхо, справедливо.

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

Bfgeshka ★★★★★
()

А если на Си не пишу, но мнение имею?

Что оно делает? Присваивает a=b и выполняет условие для всех a!=0?

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

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

В общем, и так и так мне не нравится. Но категорически против выступать не могу, потому что не сишник и вообще не программист.

Vidrele ★★★★★
()

Куда отнести тех, кто Си иногда пользуется, но не сразу разглядел подвох в этой конструкции? :)

question4 ★★★★★
()
Ответ на: комментарий от firkax

Добавил уточнение в первый пункт. Или лучше отдельным сделать?

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

question4 ★★★★★
()

Ну вот я не то, чтобы нуб, но чем больше программирую, тем больший приоритет отдаю понятности кода. А обсуждаемая конструкция всё-таки способствует запутыванию, особенно если код будет читать больше одного человека. Мне что выбирать? «В мой стиль не вписывается»? Так оно тоже не совсем то.

не-булевы выражения (речь тут не конкретно про присваивание) в качестве условия if вообще так или иначе не совсем нормальная ситуация

Ну есть ситуация, когда a и f сами по себе булевы (одно условие выводится из нескольких других). Я не скажу, что это прямо повседневная ситуация, но вообще попадается, и не сказать, что очень редко.

hobbit ★★★★★
()
Последнее исправление: hobbit (всего исправлений: 1)
Ответ на: комментарий от hobbit

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

Если формулировка варианта неудачная, придумай другую (я не знаю какую, да ещё и так чтобы она не сильно длинная была).

Про булевы - если это всё дописывать во варианты ответа они ещё длиннее станут.

firkax ★★★★★
() автор топика
Ответ на: комментарий от firkax

Упомянутый вариант означает, что вообще ты такую конструкцию допускаешь (в чужом коде - не ужасаешься от неё итд), но сам не пишешь т.к. см. выше.

Пожалуй, да, это наиболее точно отображает моё видение.

hobbit ★★★★★
()

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

Иной ценности я в такой конструкции не нахожу.

a1ba ★★★★
()

Предлагаю мнения об этом разделить на два типа: - код должен быть максимально всратым и эзотеричным - код должен быть максимально близок к учебникам Вирта и Ершова.

Я за второй подход, поэтому если бы надо было такую хрень писать, я бы использовал

#include <stdbool.h>

if((a=f)==true) {
...
}
- хотя это не корректно, поэтому - а вообще вообще бы избегал операторов на месте выражений.

Shadow ★★★★★
()
Последнее исправление: Shadow (всего исправлений: 1)
Ответ на: комментарий от Shadow

а вообще вообще бы избегал операторов на месте выражений.

Иногда удобно что-то присвоить и тут же проверить на ноль (true/false), но в этом месте настолько легко сделать ошибку, причём не обязательно сразу, а возможно в будущем при модификации кода, что лучше действительно в скобки оборачивать и записать явное сравнение.

anonymous_incognito ★★★★★
()

Переставил местами варианты ответов и чуть переделал формулировки. В предыдущей версии вариантов опасаюсь что тыкали бы не тот ответ, не дочитав до конца все варианты.

firkax ★★★★★
() автор топика

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

Feonis ★★★
()
Ответ на: комментарий от Feonis

Да, пожалуй к пхп вопрос тоже можно применить, он в этом отношении почти полностью аналогичен Си.

firkax ★★★★★
() автор топика

другой вариант (напишу в комментариях)

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

Аргументация. Присваивание внутри оператора if не добавит инструкций процессору, зато снизит читаемость кода. Более того, код if(a=f) может быть воспринят другим программистом как ошибка и заменён на if(a==f) со всеми вытекающими.

Лично по моему мнению запись должна быть такой:

a = f;
if( a )

Такой код имеет одназначную трактовку: сначала идёт присваивание, а потом проверка. Оригинальный же код может поставить в ступор начинающих программистов или воспринят как опечатка.

Дополнительные скобки в коде if((a=f)) также ухудшают читаемость кода, особенно в сложных условиях.

u5er ★★★
()

Собираюсь подтвердить завтра…

…И всё-таки, мне кажется, нужен мультивыбор. Естественно, не для того, чтобы люди выбирали взаимоисключающие варианты (они тут есть), а скорее, для того, что внизу списка. Например, варианты «у всех бывают опечатки» и «снижает читаемость кода», по-моему, друг друга не исключают.

hobbit ★★★★★
()
Ответ на: комментарий от hobbit

По-моему такой мультивыбор только запутает статистику. Эти варианты и так не имеют чёткой границы, а с мультивыбором появится ещё третий вида «и то и то». Проще тогда их объединить в один. Но выше было пожелание на тему «один мне не подходит, нужен второй». Лучше выбирать тот, причина которого приоритетна. Один - «боюсь опечататься», второй - «опечататься не боюсь, но некрасиво и мешает коллективу».

firkax ★★★★★
() автор топика
Последнее исправление: firkax (всего исправлений: 1)
Ответ на: комментарий от firkax

Стоп, я ошибся, неделя истекает не 17го, а 19го. Ещё 2 дня.

hobbit ★★★★★
()

А ещё я хочу в заголовке к Си добавить ещё и C++. Синтаксис if у них одинаковый, присваивание и сравнение тоже, плюсы только дают больше способов выстрелить в ногу. Так что проблема актуальна для обоих языков.

А аудитория опроса сильно расширится (я даже подозреваю, что в разы). Я, например, на чистой сишке пишу крайне редко, а на плюсах почти каждый день.

hobbit ★★★★★
()
Последнее исправление: hobbit (всего исправлений: 1)

Если признать эту конструкцию недопустимой - как быть с

while (row = db->fetch()) {
  ...
}

c

a = b = c = d

и вообще с концепцией, что операция присваивания возвращает результат?

PeleWin
()

Как уже сказано, конструкция не ограничивается С/С++, имеет место (с некоторыми нюансами) во многих языках с С-like синтаксисом.

И вопрос, на самом деле, мне кажется поставленным некорректно. Нужна ли реально такая конструкция, есть ли в ней хоть какая-нибудь польза? Во времена K&R экономия строчек могла быть аргументом, сейчас об этом можно даже не упоминать.

А читаемость ухудшает знатно: и спутывание =/== при беглом чтении, и иллюзия, что присвоение будет только по условию, хотя оно будет в любом случае, и дополнительные дебри, когда там не простое присвоение, а выражение, в котором даже компилятор может запутаться и вовсе решить выкинуть часть вычислений, потому что в начале уже все равно false...

Нахрен, нахрен. Четко - вот присвоение, вот проверка. Аж две строчки вместо одной, зато глаз не запнется и не замылится.

Adamos ★★★
()
Ответ на: комментарий от PeleWin

как быть с

...широко известными паттернами, которые невозможно спутать с чем-либо другим? Да так и быть...

Очевидно же, что здесь дело именно в if и ожидаемом в нем логическом выражении.

Adamos ★★★
()
Последнее исправление: Adamos (всего исправлений: 1)

Слишком мало «осуждаю», нужно больше.

dataman ★★★★★
()

Сам профессионально на С и С++ не пишу, но за такое бил бы по рукам линейкой. У вас там чё исходники на перфоленте? Но мне вообще отсутствие отдельного булевого типа не нравится, если честно.

Alden ★★★★★
()
Последнее исправление: Alden (всего исправлений: 1)

Не погромист, зашёл просто поглазеть.

Сам проголосовал за «Другое». Не знаю зачем…

mshewzov ★★★★
()
Ответ на: комментарий от LINUX-ORG-RU

Бывает специально использую

В чем смысл использовать эту конструкцию? Почему ее использование может оказаться лучше, чем

a=f;
if(a) {
...
}
aiqu6Ait ★★★★★
()
Ответ на: комментарий от LINUX-ORG-RU

if, конечно, не while, но я, изучая язык, частенько прибегаю к while (*a++ = *b++), и я вполне себе отчëт в том, что эта конструкция делает, отдаю. А вот в if (a = b) у меня пока что необходимости не возникало, и в целом, думаю, если писать чисто для себя, то можно такое использовать, но обязательно это место прокомментировать; если же это что-то совместное, то этого надо избегать.

yars068 ★★★★★
()

Ваше отношение к конструкциям любого вида в Си и C++

Устарело.

thegoldone ★★★
()

да норм тема, всегда так делаю, а кому не нравится тот программировать не умеет

bernd ★★★★★
()

Не осуждаю, но кошерный вариант это всё же:

if ((a = b) != NULL)

и т.п.

beastie ★★★★★
()
Последнее исправление: beastie (всего исправлений: 1)
Ответ на: комментарий от CrX

But on Nov. 5, 2003, Larry McVoy noticed that there was a code change in the CVS copy that did not have a pointer to a record of approval. Investigation showed that the change had never been approved and, stranger yet, that this change did not appear in the primary BitKeeper repository at all. Further investigation determined that someone had apparently broken in (electronically) to the CVS server and inserted this change.

What did the change do? This is where it gets really interesting. The change modified the code of a Linux function called wait4, which a program could use to wait for something to happen. Specifically, it added these two lines of code:

if ((options == (__WCLONE|__WALL)) && (current->uid = 0)) retval = -EINVAL;

mumpster ★★★★★
()
Ответ на: комментарий от mumpster

Этот пример вообще мимо. Закоммитили бекдор мимо проверок, этот факт (коммит мимо проверок) заметили. Конкретное содержание коммита тут несущественно. Если бы его коммитили штатным способом и во время ревью эту штуку бы заметили или наоборот не заметили - другое дело, можно было бы обсуждать.

firkax ★★★★★
() автор топика

firkax , где в твоей теме упоминание случая с Лари Маквоем? чтоб ты баяны мне приписывал?

mumpster ★★★★★
()
Ответ на: комментарий от firkax

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

в тоже время это вполне нормальный приём в некоторых, редких случаях, примерно на уровне с goto. просто надо понимать, что ты делаешь.

поэтому я и дополнил это к мнению CrX

ну а зумерам отключить это в настройках по умолчанию, естесно

mumpster ★★★★★
()

А что мешало добавить пункт «Я не программист», или написать в описании, что опрос только для них? :) Или есть ограничения на количество вариантов в опросах?

My_quest ★★★★★
()
Ответ на: комментарий от mumpster

Повторю, это не аргумент к данной теме вообще никаким боком (может быть только нейтральным примером конструкции). С тем же успехом можно было написать «о, в бэкдоре используется if, значит к if надо относиться осторожно». Понятное дело, что взломщик пытался спрятать суть бекдора с помощью «спутывания» = и ==, но логику работы этой строчки никто по существу не анализировал, анализировали факт её появления в репе без ревью. Потому что именно на ревью бы спалилась её бекдорная сущность, если бы оно было проведено.

firkax ★★★★★
() автор топика
Последнее исправление: firkax (всего исправлений: 1)

Раньше в Сишных API на такое натыкался, но там конструкции были более явными, что-то по типу:

if ((result = CheckData(&data)) == TEST_CONST)
{
    debug_info(result, ...);
    ...
}
...
print_info(result, ...);
В Плюсах как-то сильно реже попадается, да и в большинстве случаев такие проверки можно завернуть в удобную функцию или макрос.

Dr64h ★★★★
()
Ответ на: комментарий от My_quest

Там есть пункт «не понял суть проблемы/не пишу на Си». Это как раз то. И в описании (во втором предложении) указано.

firkax ★★★★★
() автор топика
Ответ на: комментарий от a1ba

тем более внутри if нельзя определить переменную и ограничить её видимость, как в for.

Чего это нельзя? Давно можно

kvpfs_2
()

Проблема не в if(a=f) как таковой а в том что теряется смысл условия которое проверяем. Хуже только if(a=f()) когда там ещё и какие-то манипуляции происходят внутри.

ya-betmen ★★★★★
()
Последнее исправление: ya-betmen (всего исправлений: 1)
Ответ на: комментарий от ya-betmen

Ну вообще f() тут вполне подразумевалось. Буквой f функции же часто обозначают.

firkax ★★★★★
() автор топика

ЯННП

Это проверка успешности присвоения или проверка значения «a» после присвоения, то есть фактическая проверка «f»?

Radjah ★★★★★
()
Ответ на: комментарий от Radjah

Это вычисление выражения f, запись результата в a и сразу же условие на предмет того ноль там или нет. Но обращу внимание что пункт «не понял» в ответах тоже есть.

firkax ★★★★★
() автор топика
Последнее исправление: firkax (всего исправлений: 1)
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.