Есть ли прагматическая причина использовать «if (0 == p)» вместо «if (! p)»? - PullRequest
21 голосов
/ 04 марта 2011

Я склонен писать операторы if, используя оператор логического отрицания:

if (!p)
    some_code();

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

if (FOO == p)
    some_code();

, где FOO является одним из false , FALSE , 0 , 0.0 , NULL и т. Д.

Я предпочитаю короткую форму, потому что она:

  • operator!= дружелюбная
  • generic programming дружелюбная
  • лаконичная (и даже красивее , как по мне)

Каковы прагматичные преимущества написания этого иначе (если есть)?

Ответы [ 12 ]

24 голосов
/ 04 марта 2011

Для контраста @ ответ Эрика Я бы сказал, используйте ! для удобства чтения.Если вы обнаружите, что пропускаете это, то проверьте свои глаза.Что дальше?Избегайте 1, используйте 3 - 2 вместо?

12 голосов
/ 04 марта 2011

Это зависит от того, что представляет p.

Если p представляет логическое / логическое значение, тогда (!p) кажется наиболее подходящим - сравнивать с «FALSE» обычно не рекомендуется.Я не ожидаю, что это будет предметом больших споров.

Если p представляет значение, такое как счетчик, то (p == 0) или (0 == p) кажется подходящим.(Между этими двумя обычно идут горячие дебаты. Я считаю, что первое более читабельно, но второе позволяет избежать некоторых очень серьезных ошибок.) Кроме того, какой из двух вариантов лучше, я не ожидаю, что это будет дискуссия (как в, он должен сравниваться с 0.)

Если p представляет указатель, то у вас есть некоторые проблемы.Компетентный программист C ++ должен знать, что (!p) скажет вам, является ли он нулевым или нет.Тем не менее, идея читабельности этой темы является серой областью, и я считаю, что это весьма спорная дискуссия.

12 голосов
/ 04 марта 2011

Используйте (0 == p) или (p == 0) для удобства чтения. Это ! легче на первый взгляд упустить, чем == 0

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

8 голосов
/ 04 марта 2011

Некоторые утверждают, что прагматическое преимущество заключается в том, что программистам будет легче понять, если вы будете явно сравнивать с NULL, FALSE, 0 и т. Д., Тогда как логический оператор может сбивать с толку людей, которые не понимают, как неявные преобразования и логические значения работают в C / C ++.

(Отказ от ответственности: я сам не разделяю эту точку зрения. if (p) ... и if (!p)... - идиоматические способы выразить это в C и C ++, и программисты, которые испытывают затруднения при их понимании, не имеют никакого отношения к коду C или C ++. Комментарий Хита Ханникута мертв.)

2 голосов
/ 07 марта 2011

Одно из пока еще не упомянутых преимуществ версии if (!Foo) заключается в том, что она будет работать с классами, использующими safe bool idiom .В классах, которые реализуют это, операторы сравнения классов не будут работать (например, Foo==0 будет неопределенным), но !Foo вызовет оператор преобразования в Foo, возвращая указатель на функцию-член (или нулевой указатель, если Foo должно бытьсчитается ложным).Ряд классов Boost, таких как shared_ptr, используют эту технику.

2 голосов
/ 04 марта 2011

Лично мне немного надоело неявное преобразование из int в логическое значение.Я не думаю, что это добавляет много к языку C больше.В C89, где нет логического типа, совершенно разумно использовать целое число в качестве логического, и в этом случае преобразование приводит к красивому коду.Я понимаю, почему его нельзя удалить, особенно когда речь идет о библиотеках, которые по причинам совместимости нельзя изменить, чтобы они возвращали логическое значение, а теперь оно есть.Но я, конечно, не думаю, что его следует использовать во всех случаях.

Иногда целочисленное значение 0 означает «нет одного», но иногда оно означает «есть один, и он равен нулю».Так что я доволен:

users = get_number_of_users();
if (users) {
    // there are users
    ...
} else {
    // there aren't users
}

Я совсем не заинтересован в:

length = strlen(ptr);
if (length) {
    // there is length? OK, sort of...
} else {
    // there isn't length? No, wait, there *is* a length, that length is 0
}

Так что у вас есть прагматическая причина написать if (length == 0) вместо if (!length),«Если не длина» не имеет смысла в английском , поэтому не обязательно то, что вы должны писать в коде.

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

1 голос
/ 04 марта 2011

Если языком является C и если p является указателем, тогда следует избегать (p) и if (! P).

C (язык) не указывает, что нулевой указатель будетлогическое значение falseВ нем говорится, что 0, приведенное к указателю (неявно или явно), даст нулевой указатель.

Поэтому тестирование p вместо p == NULL не обязательно одинаково, а на некоторых старых аппаратных средствах они определенноне то же самое, поскольку нулевой указатель на самом деле является указателем на конкретную страницу памяти.

Однако вы можете гарантировать, что 0 и, следовательно, NULL равны нулевому указателю, поскольку C говорит, что они должны быть.

1 голос
/ 04 марта 2011

Я бы поставил пробел до и после!: ( ! p) так! выделяется Но я бы ограничил это использование только целочисленными типами, включая указатели. Я бы использовал == для чисел с плавающей запятой, потому что это заставит вас и других сделать паузу и подумать, действительно ли 0.0 == p уместно по сравнению с указанием допуска.

Если p является экземпляром класса, ( ! p) должен использоваться определением оператора! чтобы избежать неявного преобразования с 0.0 == p.

1 голос
/ 04 марта 2011

В действительно сложных условных выражениях использование явного == может помочь сделать его более читабельным. К сожалению, он также открывает дверь для записи x = 0 вместо x == 0, но вы можете избежать этого, написав вместо этого 0 == x (так что 0 = x выдаст ошибку).

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

0 голосов
/ 04 марта 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...