Подтвердить что ты не робот

Есть ли прагматическая причина использовать "if (0 == p)" вместо "if (! p)"?

Я склонен писать операторы if с помощью оператора логического отрицания:

if (!p)
    some_code();

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

if (FOO == p)
    some_code();

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

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

  • operator!= friendly
  • generic programming friendly
  • лаконичный (и даже более красивый, как и я)

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

Ответ 3

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

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

Ответ 4

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

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

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

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

Ответ 5

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

Иногда целочисленное значение 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.

Ответ 6

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

Ответ 7

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

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

Ответ 8

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

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

Ответ 9

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

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

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

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

Ответ 10

единственная прагматическая причина, по которой я вижу, что во втором случае тип значений, рассмотренных для сравнения, более явный (es. foo == null foo - тип ponter,! foo не может сказать, является ли это указателем, bool и т.д.)

Ответ 11

С if (0 == p) вы вынуждаете сравнение вводить это "если область" в этом случае. Я имею в виду, будет ясно, что вы хотите сделать это в случае p is equals 0. Просто используя (!p), он не будет явным, что вы хотите знать. Это может быть null, false и т.д.

Ответ 12

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